diff --git a/common/config/environment.go b/common/config/environment.go
new file mode 100644
index 0000000000..998f0beefd
--- /dev/null
+++ b/common/config/environment.go
@@ -0,0 +1,104 @@
+/*
+ * 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 (
+ "container/list"
+ "strings"
+ "sync"
+)
+
+// There is dubbo.properties file and application level config center configuration which higner than normal config center in java. So in java the
+// configuration sequence will be config center > application level config center > dubbo.properties > spring bean configuration.
+// But in go, neither the dubbo.properties file or application level config center configuration will not support for the time being.
+// We just have config center configuration which can override configuration in consumer.yaml & provider.yaml.
+// But for add these features in future ,I finish the environment struct following Environment class in java.
+type Environment struct {
+ configCenterFirst bool
+ externalConfigs sync.Map
+ externalConfigMap sync.Map
+}
+
+var (
+ instance *Environment
+ once sync.Once
+)
+
+func GetEnvInstance() *Environment {
+ once.Do(func() {
+ instance = &Environment{configCenterFirst: true}
+ })
+ return instance
+}
+
+//func (env *Environment) SetConfigCenterFirst() {
+// env.configCenterFirst = true
+//}
+
+//func (env *Environment) ConfigCenterFirst() bool {
+// return env.configCenterFirst
+//}
+
+func (env *Environment) UpdateExternalConfigMap(externalMap map[string]string) {
+ for k, v := range externalMap {
+ env.externalConfigMap.Store(k, v)
+ }
+}
+
+func (env *Environment) Configuration() *list.List {
+ list := list.New()
+ memConf := newInmemoryConfiguration()
+ memConf.setProperties(env.externalConfigMap)
+ list.PushBack(memConf)
+ return list
+}
+
+type InmemoryConfiguration struct {
+ store sync.Map
+}
+
+func newInmemoryConfiguration() *InmemoryConfiguration {
+ return &InmemoryConfiguration{}
+}
+func (conf *InmemoryConfiguration) setProperties(p sync.Map) {
+ conf.store = p
+}
+
+func (conf *InmemoryConfiguration) GetProperty(key string) (bool, string) {
+ v, ok := conf.store.Load(key)
+ if ok {
+ return true, v.(string)
+ }
+ return false, ""
+
+}
+
+func (conf *InmemoryConfiguration) GetSubProperty(subKey string) map[string]struct{} {
+ properties := make(map[string]struct{})
+ conf.store.Range(func(key, value interface{}) bool {
+ if idx := strings.Index(key.(string), subKey); idx >= 0 {
+ after := key.(string)[idx+len(subKey):]
+ if i := strings.Index(after, "."); i >= 0 {
+ properties[after[0:strings.Index(after, ".")]] = struct{}{}
+ }
+
+ }
+ return true
+ })
+ return properties
+}
diff --git a/common/config/environment_test.go b/common/config/environment_test.go
new file mode 100644
index 0000000000..ab7cafae89
--- /dev/null
+++ b/common/config/environment_test.go
@@ -0,0 +1,52 @@
+/*
+ * 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 (
+ "testing"
+)
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetEnvInstance(t *testing.T) {
+ GetEnvInstance()
+ assert.NotNil(t, instance)
+}
+
+func TestEnvironment_UpdateExternalConfigMap(t *testing.T) {
+ GetEnvInstance().UpdateExternalConfigMap(map[string]string{"1": "2"})
+ v, ok := GetEnvInstance().externalConfigMap.Load("1")
+ assert.True(t, ok)
+ assert.Equal(t, "2", v)
+}
+
+func TestEnvironment_ConfigurationAndGetProperty(t *testing.T) {
+ GetEnvInstance().UpdateExternalConfigMap(map[string]string{"1": "2"})
+ list := GetEnvInstance().Configuration()
+ ok, v := list.Front().Value.(*InmemoryConfiguration).GetProperty("1")
+ assert.True(t, ok)
+ assert.Equal(t, "2", v)
+}
+
+func TestInmemoryConfiguration_GetSubProperty(t *testing.T) {
+ GetEnvInstance().UpdateExternalConfigMap(map[string]string{"123": "2"})
+ list := GetEnvInstance().Configuration()
+ m := list.Front().Value.(*InmemoryConfiguration).GetSubProperty("1")
+
+ assert.Equal(t, struct{}{}, m["123"])
+}
diff --git a/common/constant/default.go b/common/constant/default.go
index f67f2158fd..d2c6226188 100644
--- a/common/constant/default.go
+++ b/common/constant/default.go
@@ -17,6 +17,9 @@
package constant
+const (
+ DUBBO = "dubbo"
+)
const (
DEFAULT_WEIGHT = 100 //
DEFAULT_WARMUP = 10 * 60 // in java here is 10*60*1000 because of System.currentTimeMillis() is measured in milliseconds & in go time.Unix() is second
diff --git a/common/constant/key.go b/common/constant/key.go
index e82a41aa4a..3980a483e0 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -73,3 +73,11 @@ const (
CONFIG_NAMESPACE_KEY = "config.namespace"
CONFIG_TIMEOUT_KET = "config.timeout"
)
+const (
+ RegistryConfigPrefix = "dubbo.registries."
+ ReferenceConfigPrefix = "dubbo.reference."
+ ServiceConfigPrefix = "dubbo.service."
+ ProtocolConfigPrefix = "dubbo.protocols."
+ ProviderConfigPrefix = "dubbo.provider."
+ ConsumerConfigPrefix = "dubbo.consumer."
+)
diff --git a/common/extension/config_center_factory.go b/common/extension/config_center_factory.go
new file mode 100644
index 0000000000..82e0ef6ebc
--- /dev/null
+++ b/common/extension/config_center_factory.go
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package extension
+
+import (
+ "github.com/apache/dubbo-go/config_center"
+)
+
+var (
+ configCenterFactories = make(map[string]func() config_center.DynamicConfigurationFactory)
+)
+
+func SetConfigCenterFactory(name string, v func() config_center.DynamicConfigurationFactory) {
+ configCenterFactories[name] = v
+}
+
+func GetConfigCenterFactory(name string) config_center.DynamicConfigurationFactory {
+ if configCenterFactories[name] == nil {
+ panic("config center for " + name + " is not existing, make sure you have import the package.")
+ }
+ return configCenterFactories[name]()
+}
diff --git a/common/url.go b/common/url.go
index 9249dd055a..a6223d547c 100644
--- a/common/url.go
+++ b/common/url.go
@@ -164,6 +164,13 @@ func NewURL(ctx context.Context, urlString string, opts ...option) (URL, error)
}
//rawUrlString = "//" + rawUrlString
+ if strings.Index(rawUrlString, "//") < 0 {
+ t := URL{baseUrl: baseUrl{ctx: ctx}}
+ for _, opt := range opts {
+ opt(&t)
+ }
+ rawUrlString = t.Protocol + "://" + rawUrlString
+ }
serviceUrl, err = url.Parse(rawUrlString)
if err != nil {
return s, perrors.Errorf("url.Parse(url string{%s}), error{%v}", rawUrlString, err)
@@ -186,21 +193,9 @@ func NewURL(ctx context.Context, urlString string, opts ...option) (URL, error)
return s, perrors.Errorf("net.SplitHostPort(Url.Host{%s}), error{%v}", s.Location, err)
}
}
- //
- //timeoutStr := s.Params.Get("timeout")
- //if len(timeoutStr) == 0 {
- // timeoutStr = s.Params.Get("default.timeout")
- //}
- //if len(timeoutStr) != 0 {
- // timeout, err := strconv.Atoi(timeoutStr)
- // if err == nil && timeout != 0 {
- // s.Timeout = time.Duration(timeout * 1e6) // timeout unit is millisecond
- // }
- //}
for _, opt := range opts {
opt(&s)
}
- //fmt.Println(s.String())
return s, nil
}
diff --git a/common/url_test.go b/common/url_test.go
index bae37237f1..272c179b0d 100644
--- a/common/url_test.go
+++ b/common/url_test.go
@@ -81,6 +81,33 @@ func TestURL(t *testing.T) {
"ZX&pid=1447&revision=0.0.1&side=provider&timeout=3000×tamp=1556509797245", u.String())
}
+func TestURLWithoutSchema(t *testing.T) {
+ u, err := NewURL(context.TODO(), "@127.0.0.1:20000/com.ikurento.user.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", WithProtocol("dubbo"))
+ assert.NoError(t, err)
+
+ assert.Equal(t, "/com.ikurento.user.UserProvider", u.Path)
+ assert.Equal(t, "127.0.0.1:20000", u.Location)
+ assert.Equal(t, "dubbo", u.Protocol)
+ assert.Equal(t, "127.0.0.1", u.Ip)
+ assert.Equal(t, "20000", u.Port)
+ assert.Equal(t, URL{}.Methods, u.Methods)
+ assert.Equal(t, "", u.Username)
+ assert.Equal(t, "", u.Password)
+ assert.Equal(t, "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&t"+
+ "imestamp=1556509797245", u.Params.Encode())
+
+ assert.Equal(t, "dubbo://:@127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&application=BDTServi"+
+ "ce&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&environment=dev&interface=com.ikure"+
+ "nto.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", u.String())
+}
+
func TestURL_URLEqual(t *testing.T) {
u1, err := NewURL(context.TODO(), "dubbo://:@127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0")
assert.NoError(t, err)
diff --git a/config/application_config.go b/config/application_config.go
index ae9716d2d0..af4ffd6acf 100644
--- a/config/application_config.go
+++ b/config/application_config.go
@@ -17,11 +17,23 @@
package config
+import "github.com/apache/dubbo-go/common/constant"
+
type ApplicationConfig struct {
- Organization string `yaml:"organization" json:"organization,omitempty"`
- Name string `yaml:"name" json:"name,omitempty"`
- Module string `yaml:"module" json:"module,omitempty"`
- Version string `yaml:"version" json:"version,omitempty"`
- Owner string `yaml:"owner" json:"owner,omitempty"`
- Environment string `yaml:"environment" json:"environment,omitempty"`
+ Organization string `yaml:"organization" json:"organization,omitempty" property:"organization"`
+ Name string `yaml:"name" json:"name,omitempty" property:"name"`
+ Module string `yaml:"module" json:"module,omitempty" property:"module"`
+ Version string `yaml:"version" json:"version,omitempty" property:"version"`
+ Owner string `yaml:"owner" json:"owner,omitempty" property:"owner"`
+ Environment string `yaml:"environment" json:"environment,omitempty" property:"environment"`
+}
+
+func (*ApplicationConfig) Prefix() string {
+ return constant.DUBBO + ".application."
+}
+func (c *ApplicationConfig) Id() string {
+ return ""
+}
+func (c *ApplicationConfig) SetId(id string) {
+
}
diff --git a/config/base_config.go b/config/base_config.go
new file mode 100644
index 0000000000..19acea2fd6
--- /dev/null
+++ b/config/base_config.go
@@ -0,0 +1,262 @@
+/*
+ * 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 (
+ "context"
+ "reflect"
+ "strconv"
+)
+import (
+ perrors "github.com/pkg/errors"
+)
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/common/config"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/common/logger"
+ "github.com/apache/dubbo-go/config_center"
+)
+
+type multiConfiger interface {
+ Prefix() string
+}
+
+type BaseConfig struct {
+ ConfigCenterConfig *ConfigCenterConfig `yaml:"config_center" json:"config_center,omitempty"`
+ configCenterUrl *common.URL
+ prefix string
+ fatherConfig interface{}
+}
+
+func (c *BaseConfig) startConfigCenter(ctx context.Context) error {
+ url, err := common.NewURL(ctx, c.ConfigCenterConfig.Address, common.WithProtocol(c.ConfigCenterConfig.Protocol))
+ if err != nil {
+ return err
+ }
+ c.configCenterUrl = &url
+ if c.prepareEnvironment() != nil {
+ return perrors.WithMessagef(err, "start config center error!")
+ }
+ //c.fresh()
+ return err
+}
+
+func (c *BaseConfig) prepareEnvironment() error {
+
+ factory := extension.GetConfigCenterFactory(c.ConfigCenterConfig.Protocol)
+ dynamicConfig, err := factory.GetDynamicConfiguration(c.configCenterUrl)
+ if err != nil {
+ logger.Errorf("Get dynamic configuration error , error message is %v", err)
+ return perrors.WithStack(err)
+ }
+ content, err := dynamicConfig.GetConfig(c.ConfigCenterConfig.ConfigFile, config_center.WithGroup(c.ConfigCenterConfig.Group))
+ if err != nil {
+ logger.Errorf("Get config content in dynamic configuration error , error message is %v", err)
+ return perrors.WithStack(err)
+ }
+ mapContent, err := dynamicConfig.Parser().Parse(content)
+ if err != nil {
+ return perrors.WithStack(err)
+ }
+ config.GetEnvInstance().UpdateExternalConfigMap(mapContent)
+ return nil
+}
+
+func getKeyPrefix(val reflect.Value, id reflect.Value) string {
+ var (
+ prefix string
+ idStr string
+ )
+ if id.Kind() == reflect.String {
+ idStr = id.Interface().(string)
+ }
+
+ if val.CanAddr() {
+ prefix = val.Addr().MethodByName("Prefix").Call(nil)[0].String()
+ } else {
+ prefix = val.MethodByName("Prefix").Call(nil)[0].String()
+ }
+
+ if idStr != "" {
+ return prefix + idStr + "."
+ } else {
+ return prefix
+ }
+}
+
+func setFieldValue(val reflect.Value, id reflect.Value, config *config.InmemoryConfiguration) {
+ for i := 0; i < val.NumField(); i++ {
+ if key := val.Type().Field(i).Tag.Get("property"); key != "-" && key != "" {
+ f := val.Field(i)
+ if f.IsValid() {
+ setBaseValue := func(f reflect.Value) {
+ ok, value := config.GetProperty(getKeyPrefix(val, id) + key)
+ if ok {
+ if f.Kind() == reflect.Int64 {
+ x, err := strconv.Atoi(value)
+ if err != nil {
+ logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
+ val.Type().Name(), val.Type().Field(i).Name, err)
+ } else {
+ if !f.OverflowInt(int64(x)) {
+ f.SetInt(int64(x))
+ } else {
+ logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
+ val.Type().Name(), val.Type().Field(i).Name, perrors.Errorf("the int64 value {%v} from config center is overflow", int64(x)))
+ }
+ }
+
+ }
+
+ if f.Kind() == reflect.String {
+ f.SetString(value)
+ }
+ if f.Kind() == reflect.Bool {
+ x, err := strconv.ParseBool(value)
+ if err != nil {
+ logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
+ val.Type().Name(), val.Type().Field(i).Name, err)
+ }
+ f.SetBool(x)
+ }
+ if f.Kind() == reflect.Float64 {
+ x, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
+ val.Type().Name(), val.Type().Field(i).Name, err)
+ } else {
+ if !f.OverflowFloat(x) {
+ f.SetFloat(x)
+ } else {
+ logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
+ val.Type().Name(), val.Type().Field(i).Name, perrors.Errorf("the float64 value {%v} from config center is overflow", x))
+ }
+ }
+ }
+ }
+
+ }
+
+ setBaseValue(f)
+ if f.Kind() == reflect.Ptr {
+ if f.Elem().Kind() == reflect.Struct {
+ setFieldValue(f.Elem(), reflect.Value{}, config)
+ } else {
+ setBaseValue(f.Elem())
+ }
+ }
+
+ if f.Kind() == reflect.Struct {
+ setFieldValue(f, reflect.Value{}, config)
+ }
+ if f.Kind() == reflect.Slice {
+ for i := 0; i < f.Len(); i++ {
+ e := f.Index(i)
+ if e.Kind() == reflect.Ptr {
+ if e.Elem().Kind() == reflect.Struct {
+ setFieldValue(e.Elem(), reflect.Value{}, config)
+ } else {
+ setBaseValue(e.Elem())
+ }
+ }
+
+ }
+
+ }
+ if f.Kind() == reflect.Map {
+
+ //initiate config
+ s := reflect.New(f.Type().Elem().Elem())
+ prefix := s.MethodByName("Prefix").Call(nil)[0].String()
+ m := config.GetSubProperty(prefix)
+ for k := range m {
+ f.SetMapIndex(reflect.ValueOf(k), reflect.New(f.Type().Elem().Elem()))
+ }
+ //iter := f.MapRange()
+
+ for _, k := range f.MapKeys() {
+ v := f.MapIndex(k)
+ if v.Kind() == reflect.Ptr {
+ if v.Elem().Kind() == reflect.Struct {
+ setFieldValue(v.Elem(), k, config)
+ } else {
+ setBaseValue(v.Elem())
+ }
+ }
+
+ }
+ }
+
+ }
+ }
+ }
+}
+func (c *BaseConfig) fresh() {
+ configList := config.GetEnvInstance().Configuration()
+ config := configList.Front().Value.(*config.InmemoryConfiguration)
+
+ //reflect to init struct
+ tp := reflect.ValueOf(c.fatherConfig).Elem().Type()
+ initializeStruct(tp, reflect.ValueOf(c.fatherConfig).Elem())
+
+ val := reflect.Indirect(reflect.ValueOf(c.fatherConfig))
+ setFieldValue(val, reflect.Value{}, config)
+}
+
+func (c *BaseConfig) SetFatherConfig(fatherConfig interface{}) {
+ c.fatherConfig = fatherConfig
+}
+
+func initializeStruct(t reflect.Type, v reflect.Value) {
+ if v.Kind() == reflect.Struct {
+ for i := 0; i < v.NumField(); i++ {
+ f := v.Field(i)
+ ft := t.Field(i)
+
+ if ft.Tag.Get("property") != "" {
+ switch ft.Type.Kind() {
+ case reflect.Map:
+ if f.IsNil() {
+ f.Set(reflect.MakeMap(ft.Type))
+ }
+ case reflect.Slice:
+ if f.IsNil() {
+ f.Set(reflect.MakeSlice(ft.Type, 0, 0))
+ }
+ case reflect.Chan:
+ if f.IsNil() {
+ f.Set(reflect.MakeChan(ft.Type, 0))
+ }
+ case reflect.Struct:
+ if f.IsNil() {
+ initializeStruct(ft.Type, f)
+ }
+ case reflect.Ptr:
+ if f.IsNil() {
+ fv := reflect.New(ft.Type.Elem())
+ initializeStruct(ft.Type.Elem(), fv.Elem())
+ f.Set(fv)
+ }
+ default:
+ }
+ }
+
+ }
+ }
+
+}
diff --git a/config/base_config_test.go b/config/base_config_test.go
new file mode 100644
index 0000000000..7676a11d02
--- /dev/null
+++ b/config/base_config_test.go
@@ -0,0 +1,258 @@
+/*
+ * 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 (
+ "context"
+ "fmt"
+ "reflect"
+ "testing"
+)
+import (
+ "github.com/stretchr/testify/assert"
+)
+import (
+ "github.com/apache/dubbo-go/common/config"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/config_center"
+)
+
+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.consumer.check"] = "false"
+ mockMap["dubbo.application.name"] = "dubbo"
+
+ config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
+
+ father := &ConsumerConfig{
+ Check: &[]bool{true}[0],
+ ApplicationConfig: &ApplicationConfig{
+ Organization: "dubbo_org",
+ Name: "dubbo",
+ Module: "module",
+ Version: "2.6.0",
+ Owner: "dubbo",
+ Environment: "test"},
+ Registries: map[string]*RegistryConfig{
+ //"shanghai_reg1": {
+ // id: "shanghai_reg1",
+ // Protocol: "mock",
+ // TimeoutStr: "2s",
+ // Group: "shanghai_idc",
+ // Address: "127.0.0.1:2181",
+ // Username: "user1",
+ // Password: "pwd1",
+ //},
+ "shanghai_reg2": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "shanghai_idc",
+ Address: "127.0.0.2:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ "hangzhou_reg1": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "hangzhou_idc",
+ Address: "127.0.0.3:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ "hangzhou_reg2": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "hangzhou_idc",
+ Address: "127.0.0.4:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ },
+ References: map[string]*ReferenceConfig{
+ "MockService": {
+ InterfaceName: "MockService",
+ Protocol: "mock",
+ Cluster: "failover",
+ Loadbalance: "random",
+ Retries: 3,
+ Group: "huadong_idc",
+ Version: "1.0.0",
+ Methods: []*MethodConfig{
+ {
+ InterfaceId: "MockService",
+ InterfaceName: "MockService",
+ Name: "GetUser",
+ Retries: 2,
+ Loadbalance: "random",
+ },
+ {InterfaceId: "MockService",
+ InterfaceName: "MockService",
+ Name: "GetUser1",
+ Retries: 2,
+ Loadbalance: "random",
+ },
+ },
+ },
+ },
+ }
+
+ c.SetFatherConfig(father)
+ c.fresh()
+ assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
+ assert.Equal(t, int64(10), father.References["MockService"].Retries)
+
+ assert.Equal(t, int64(10), father.References["MockService"].Methods[0].Retries)
+ assert.Equal(t, &[]bool{false}[0], father.Check)
+ assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
+}
+
+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.consumer.check"] = "false"
+ mockMap["dubbo.application.name"] = "dubbo"
+ mockMap["dubbo.protocols.jsonrpc1.name"] = "jsonrpc"
+ mockMap["dubbo.protocols.jsonrpc1.ip"] = "127.0.0.1"
+ mockMap["dubbo.protocols.jsonrpc1.port"] = "20001"
+
+ config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
+
+ father := &ProviderConfig{
+ ApplicationConfig: &ApplicationConfig{
+ Organization: "dubbo_org",
+ Name: "dubbo",
+ Module: "module",
+ Version: "2.6.0",
+ Owner: "dubbo",
+ Environment: "test"},
+ Registries: map[string]*RegistryConfig{
+ //"shanghai_reg1": {
+ // id: "shanghai_reg1",
+ // Protocol: "mock",
+ // TimeoutStr: "2s",
+ // Group: "shanghai_idc",
+ // Address: "127.0.0.1:2181",
+ // Username: "user1",
+ // Password: "pwd1",
+ //},
+ "shanghai_reg2": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "shanghai_idc",
+ Address: "127.0.0.2:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ "hangzhou_reg1": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "hangzhou_idc",
+ Address: "127.0.0.3:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ "hangzhou_reg2": {
+ Protocol: "mock",
+ TimeoutStr: "2s",
+ Group: "hangzhou_idc",
+ Address: "127.0.0.4:2181",
+ Username: "user1",
+ Password: "pwd1",
+ },
+ },
+ Services: map[string]*ServiceConfig{
+ "MockService": {
+ InterfaceName: "MockService",
+ Protocol: "mock",
+ Cluster: "failover",
+ Loadbalance: "random",
+ Retries: 3,
+ Group: "huadong_idc",
+ Version: "1.0.0",
+ Methods: []*MethodConfig{
+ {
+ InterfaceId: "MockService",
+ InterfaceName: "MockService",
+ Name: "GetUser",
+ Retries: 2,
+ Loadbalance: "random",
+ },
+ {InterfaceId: "MockService",
+ InterfaceName: "MockService",
+ Name: "GetUser1",
+ Retries: 2,
+ Loadbalance: "random",
+ },
+ },
+ },
+ },
+ }
+
+ c.SetFatherConfig(father)
+ c.fresh()
+ assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
+ assert.Equal(t, int64(10), father.Services["MockService"].Retries)
+
+ assert.Equal(t, int64(10), father.Services["MockService"].Methods[0].Retries)
+ assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
+ assert.Equal(t, "20001", father.Protocols["jsonrpc1"].Port)
+}
+
+func Test_startConfigCenter(t *testing.T) {
+
+ extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
+ return &config_center.MockDynamicConfigurationFactory{}
+ })
+ c := &BaseConfig{ConfigCenterConfig: &ConfigCenterConfig{
+ Protocol: "mock",
+ Address: "172.0.0.1",
+ Group: "dubbo",
+ ConfigFile: "mockDubbo.properties",
+ }}
+ err := c.startConfigCenter(context.Background())
+ assert.NoError(t, err)
+ b, v := config.GetEnvInstance().Configuration().Front().Value.(*config.InmemoryConfiguration).GetProperty("dubbo.application.organization")
+ assert.True(t, b)
+ assert.Equal(t, "ikurento.com", v)
+}
+
+func Test_initializeStruct(t *testing.T) {
+ consumerConfig := &ConsumerConfig{}
+ tp := reflect.TypeOf(ConsumerConfig{})
+ v := reflect.New(tp)
+ initializeStruct(tp, v.Elem())
+ fmt.Println(reflect.ValueOf(consumerConfig).Elem().Type().String())
+ fmt.Println(v.Elem().Type().String())
+ reflect.ValueOf(consumerConfig).Elem().Set(v.Elem())
+
+ assert.Condition(t, func() (success bool) {
+ return consumerConfig.ApplicationConfig != nil
+ })
+ assert.Condition(t, func() (success bool) {
+ return consumerConfig.Registries != nil
+ })
+ assert.Condition(t, func() (success bool) {
+ return consumerConfig.References != nil
+ })
+}
diff --git a/config/config_center_config.go b/config/config_center_config.go
new file mode 100644
index 0000000000..47efce1265
--- /dev/null
+++ b/config/config_center_config.go
@@ -0,0 +1,36 @@
+/*
+ * 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 (
+ "context"
+ "time"
+)
+
+type ConfigCenterConfig struct {
+ context context.Context
+ Protocol string `required:"true" yaml:"protocol" json:"protocol,omitempty"`
+ Address string `yaml:"address" json:"address,omitempty"`
+ Cluster string `yaml:"cluster" json:"cluster,omitempty"`
+ Group string `default:"dubbo" yaml:"group" json:"group,omitempty"`
+ Username string `yaml:"username" json:"username,omitempty"`
+ Password string `yaml:"password" json:"password,omitempty"`
+ ConfigFile string `default:"dubbo.properties" yaml:"config_file" json:"config_file,omitempty"`
+ TimeoutStr string `yaml:"timeout" json:"timeout,omitempty"`
+ timeout time.Duration
+}
diff --git a/config/config_loader.go b/config/config_loader.go
index e8c3951bcf..86260c8673 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -19,19 +19,11 @@ package config
import (
"fmt"
- "io/ioutil"
"log"
"os"
- "path"
- "strings"
"time"
)
-import (
- perrors "github.com/pkg/errors"
- "gopkg.in/yaml.v2"
-)
-
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
@@ -48,14 +40,12 @@ var (
// loaded comsumer & provider config from xxx.yml, and log config from xxx.xml
// Namely: dubbo.comsumer.xml & dubbo.provider.xml in java dubbo
func init() {
-
var (
confConFile, confProFile string
)
confConFile = os.Getenv(constant.CONF_CONSUMER_FILE_PATH)
confProFile = os.Getenv(constant.CONF_PROVIDER_FILE_PATH)
-
if errCon := consumerInit(confConFile); errCon != nil {
log.Printf("[consumerInit] %#v", errCon)
consumerConfig = nil
@@ -66,172 +56,33 @@ func init() {
}
}
-func consumerInit(confConFile string) error {
- if confConFile == "" {
- return perrors.Errorf("application configure(consumer) file name is nil")
- }
-
- if path.Ext(confConFile) != ".yml" {
- return perrors.Errorf("application configure file name{%v} suffix must be .yml", confConFile)
- }
-
- confFileStream, err := ioutil.ReadFile(confConFile)
- if err != nil {
- return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confConFile, perrors.WithStack(err))
- }
- consumerConfig = &ConsumerConfig{}
- err = yaml.Unmarshal(confFileStream, consumerConfig)
- if err != nil {
- return perrors.Errorf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
- }
-
- if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
- return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
- }
- if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
- return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
- }
-
- logger.Debugf("consumer config{%#v}\n", consumerConfig)
- return nil
-}
-
-func providerInit(confProFile string) error {
- if confProFile == "" {
- return perrors.Errorf("application configure(provider) file name is nil")
- }
-
- if path.Ext(confProFile) != ".yml" {
- return perrors.Errorf("application configure file name{%v} suffix must be .yml", confProFile)
- }
-
- confFileStream, err := ioutil.ReadFile(confProFile)
- if err != nil {
- return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confProFile, perrors.WithStack(err))
- }
- providerConfig = &ProviderConfig{}
- err = yaml.Unmarshal(confFileStream, providerConfig)
- if err != nil {
- return perrors.Errorf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
- }
-
- logger.Debugf("provider config{%#v}\n", providerConfig)
- return nil
-}
-
-/////////////////////////
-// consumerConfig
-/////////////////////////
-
-type ConsumerConfig struct {
- Filter string `yaml:"filter" json:"filter,omitempty"`
-
- // client
- Connect_Timeout string `default:"100ms" yaml:"connect_timeout" json:"connect_timeout,omitempty"`
- ConnectTimeout time.Duration
-
- Request_Timeout string `yaml:"request_timeout" default:"5s" json:"request_timeout,omitempty"`
- RequestTimeout time.Duration
- ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty"`
- Check *bool `yaml:"check" json:"check,omitempty"`
- // application
- ApplicationConfig ApplicationConfig `yaml:"application_config" json:"application_config,omitempty"`
- Registries []RegistryConfig `yaml:"registries" json:"registries,omitempty"`
- References []ReferenceConfig `yaml:"references" json:"references,omitempty"`
- ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty"`
-}
-
-type ReferenceConfigTmp struct {
- Service string `required:"true" yaml:"service" json:"service,omitempty"`
- Registries []RegistryConfig `required:"true" yaml:"registries" json:"registries,omitempty"`
- URLs []map[string]string
-}
-
-func SetConsumerConfig(c ConsumerConfig) {
- consumerConfig = &c
-}
-func GetConsumerConfig() ConsumerConfig {
- if consumerConfig == nil {
- logger.Warnf("consumerConfig is nil!")
- return ConsumerConfig{}
- }
- return *consumerConfig
-}
-
-/////////////////////////
-// providerConfig
-/////////////////////////
-
-type ProviderConfig struct {
- Filter string `yaml:"filter" json:"filter,omitempty"`
- ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty"`
-
- ApplicationConfig ApplicationConfig `yaml:"application_config" json:"application_config,omitempty"`
- Registries []RegistryConfig `yaml:"registries" json:"registries,omitempty"`
- Services []ServiceConfig `yaml:"services" json:"services,omitempty"`
- Protocols []ProtocolConfig `yaml:"protocols" json:"protocols,omitempty"`
- ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty"`
-}
-
-func SetProviderConfig(p ProviderConfig) {
- providerConfig = &p
-}
-func GetProviderConfig() ProviderConfig {
- if providerConfig == nil {
- logger.Warnf("providerConfig is nil!")
- return ProviderConfig{}
- }
- return *providerConfig
-}
-
-type ProtocolConfig struct {
- Name string `required:"true" yaml:"name" json:"name,omitempty"`
- Ip string `required:"true" yaml:"ip" json:"ip,omitempty"`
- Port string `required:"true" yaml:"port" json:"port,omitempty"`
- ContextPath string `required:"true" yaml:"contextPath" json:"contextPath,omitempty"`
-}
-
-func loadProtocol(protocolsIds string, protocols []ProtocolConfig) []ProtocolConfig {
- returnProtocols := []ProtocolConfig{}
- for _, v := range strings.Split(protocolsIds, ",") {
- for _, prot := range protocols {
- if v == prot.Name {
- returnProtocols = append(returnProtocols, prot)
- }
- }
-
- }
- return returnProtocols
-}
-
-var (
- refConfigs map[string]*ReferenceConfig // record reference config loaded
- srvConfigs map[string]*ServiceConfig // record service config loaded
-)
-
// Dubbo Init
-func Load() (int, int) {
- var refMap map[string]*ReferenceConfig
- var srvMap map[string]*ServiceConfig
+func Load() {
+ var (
+ refMap map[string]*ReferenceConfig
+ srvMap map[string]*ServiceConfig
+ )
// reference config
if consumerConfig == nil {
logger.Warnf("consumerConfig is nil!")
} else {
+ if err := configCenterRefreshConsumer(); err != nil {
+ logger.Errorf("[consumer config center refresh] %#v", err)
+ }
refMap = make(map[string]*ReferenceConfig)
- length := len(consumerConfig.References)
- for index := 0; index < length; index++ {
- con := &consumerConfig.References[index]
- rpcService := GetConsumerService(con.InterfaceName)
- con.Refer()
- refMap[con.InterfaceName] = con
+ for _, ref := range consumerConfig.References {
+ rpcService := GetConsumerService(ref.InterfaceName)
+
if rpcService == nil {
- logger.Warnf("%s is not exsist!", con.InterfaceName)
+ logger.Warnf("%s is not exsist!", ref.InterfaceName)
continue
}
- con.Implement(rpcService)
- }
+ ref.Refer()
+ ref.Implement(rpcService)
+ refMap[ref.InterfaceName] = ref
+ }
//wait for invoker is available, if wait over default 3s, then panic
var count int
checkok := true
@@ -267,34 +118,31 @@ func Load() (int, int) {
if providerConfig == nil {
logger.Warnf("providerConfig is nil!")
} else {
+ if err := configCenterRefreshProvider(); err != nil {
+ logger.Errorf("[provider config center refresh] %#v", err)
+ }
srvMap = make(map[string]*ServiceConfig)
- length := len(providerConfig.Services)
- for index := 0; index < length; index++ {
- pro := &providerConfig.Services[index]
- rpcService := GetProviderService(pro.InterfaceName)
+ for _, svs := range providerConfig.Services {
+ rpcService := GetProviderService(svs.InterfaceName)
if rpcService == nil {
- logger.Warnf("%s is not exsist!", pro.InterfaceName)
+ logger.Warnf("%s is not exsist!", svs.InterfaceName)
continue
}
- pro.Implement(rpcService)
- if err := pro.Export(); err != nil {
- panic(fmt.Sprintf("service %s export failed! ", pro.InterfaceName))
+ svs.Implement(rpcService)
+ if err := svs.Export(); err != nil {
+ panic(fmt.Sprintf("service %s export failed! ", svs.InterfaceName))
}
- srvMap[pro.InterfaceName] = pro
+ srvMap[svs.InterfaceName] = svs
}
}
-
- refConfigs = refMap
- srvConfigs = srvMap
- return len(refMap), len(srvMap)
}
// get rpc service for consumer
func GetRPCService(name string) common.RPCService {
- return refConfigs[name].GetRPCService()
+ return consumerConfig.References[name].GetRPCService()
}
// create rpc service for consumer
func RPCService(service common.RPCService) {
- refConfigs[service.Service()].Implement(service)
+ providerConfig.Services[service.Service()].Implement(service)
}
diff --git a/config/config_loader_test.go b/config/config_loader_test.go
index 9d062ce2fc..bcd42a678a 100644
--- a/config/config_loader_test.go
+++ b/config/config_loader_test.go
@@ -31,6 +31,7 @@ import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/common/proxy/proxy_factory"
+ "github.com/apache/dubbo-go/config_center"
)
func TestConfigLoader(t *testing.T) {
@@ -66,11 +67,8 @@ func TestLoad(t *testing.T) {
extension.SetProtocol("registry", GetProtocol)
extension.SetCluster("registryAware", cluster_impl.NewRegistryAwareCluster)
extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
- consumerConfig.References[0].Registries = []ConfigRegistry{"shanghai_reg1"}
- refLen, svcLen := Load()
- assert.NotEqual(t, 0, refLen)
- assert.NotEqual(t, 0, svcLen)
+ Load()
assert.Equal(t, ms, GetRPCService(ms.Service()))
ms2 := &struct {
@@ -85,3 +83,35 @@ func TestLoad(t *testing.T) {
consumerConfig = nil
providerConfig = nil
}
+
+func TestConfigLoaderWithConfigCenter(t *testing.T) {
+ extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
+ return &config_center.MockDynamicConfigurationFactory{}
+ })
+
+ conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
+ assert.NoError(t, err)
+ proPath, err := filepath.Abs("./testdata/provider_config.yml")
+ assert.NoError(t, err)
+
+ assert.Nil(t, consumerConfig)
+ assert.Equal(t, ConsumerConfig{}, GetConsumerConfig())
+ assert.Nil(t, providerConfig)
+ assert.Equal(t, ProviderConfig{}, GetProviderConfig())
+
+ err = consumerInit(conPath)
+ configCenterRefreshConsumer()
+ assert.NoError(t, err)
+ err = providerInit(proPath)
+ configCenterRefreshProvider()
+ assert.NoError(t, err)
+
+ assert.NotNil(t, consumerConfig)
+ assert.NotEqual(t, ConsumerConfig{}, GetConsumerConfig())
+ assert.NotNil(t, providerConfig)
+ assert.NotEqual(t, ProviderConfig{}, GetProviderConfig())
+
+ assert.Equal(t, "BDTService", consumerConfig.ApplicationConfig.Name)
+ assert.Equal(t, "127.0.0.1:2181", consumerConfig.Registries["hangzhouzk"].Address)
+
+}
diff --git a/config/consumer_config.go b/config/consumer_config.go
new file mode 100644
index 0000000000..5d3aec18e9
--- /dev/null
+++ b/config/consumer_config.go
@@ -0,0 +1,134 @@
+/*
+ * 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 (
+ "context"
+ "io/ioutil"
+ "path"
+ "time"
+)
+import (
+ perrors "github.com/pkg/errors"
+ "gopkg.in/yaml.v2"
+)
+import (
+ "github.com/apache/dubbo-go/common/constant"
+ "github.com/apache/dubbo-go/common/logger"
+)
+
+/////////////////////////
+// consumerConfig
+/////////////////////////
+
+type ConsumerConfig struct {
+ BaseConfig `yaml:",inline"`
+ Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+ // application
+ ApplicationConfig *ApplicationConfig `yaml:"application_config" json:"application_config,omitempty" property:"application_config"`
+ // client
+ Connect_Timeout string `default:"100ms" yaml:"connect_timeout" json:"connect_timeout,omitempty" property:"connect_timeout"`
+ ConnectTimeout time.Duration
+
+ Request_Timeout string `yaml:"request_timeout" default:"5s" json:"request_timeout,omitempty" property:"request_timeout"`
+ RequestTimeout time.Duration
+ ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
+ Check *bool `yaml:"check" json:"check,omitempty" property:"check"`
+
+ Registries map[string]*RegistryConfig `yaml:"registries" json:"registries,omitempty" property:"registries"`
+ References map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
+ ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf"`
+}
+
+func (*ConsumerConfig) Prefix() string {
+ return constant.ConsumerConfigPrefix
+}
+
+func SetConsumerConfig(c ConsumerConfig) {
+ consumerConfig = &c
+}
+func GetConsumerConfig() ConsumerConfig {
+ if consumerConfig == nil {
+ logger.Warnf("consumerConfig is nil!")
+ return ConsumerConfig{}
+ }
+ return *consumerConfig
+}
+
+func consumerInit(confConFile string) error {
+ if confConFile == "" {
+ return perrors.Errorf("application configure(consumer) file name is nil")
+ }
+
+ if path.Ext(confConFile) != ".yml" {
+ return perrors.Errorf("application configure file name{%v} suffix must be .yml", confConFile)
+ }
+
+ confFileStream, err := ioutil.ReadFile(confConFile)
+ if err != nil {
+ return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confConFile, perrors.WithStack(err))
+ }
+ consumerConfig = &ConsumerConfig{}
+ err = yaml.Unmarshal(confFileStream, consumerConfig)
+ if err != nil {
+ return perrors.Errorf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
+ }
+
+ //set method interfaceId & interfaceName
+ for k, v := range consumerConfig.References {
+ //set id for reference
+ for _, n := range consumerConfig.References[k].Methods {
+ n.InterfaceName = v.InterfaceName
+ n.InterfaceId = k
+ }
+ }
+ if consumerConfig.Request_Timeout != "" {
+ if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
+ return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
+ }
+ }
+ if consumerConfig.Connect_Timeout != "" {
+ if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
+ return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
+ }
+ }
+ logger.Debugf("consumer config{%#v}\n", consumerConfig)
+ return nil
+}
+
+func configCenterRefreshConsumer() error {
+ //fresh it
+ var err error
+ if consumerConfig.ConfigCenterConfig != nil {
+ consumerConfig.SetFatherConfig(consumerConfig)
+ if err := consumerConfig.startConfigCenter(context.Background()); err != nil {
+ return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
+ }
+ consumerConfig.fresh()
+ }
+ if consumerConfig.Request_Timeout != "" {
+ if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
+ return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
+ }
+ }
+ if consumerConfig.Connect_Timeout != "" {
+ if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
+ return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
+ }
+ }
+ return err
+}
diff --git a/config/method_config.go b/config/method_config.go
new file mode 100644
index 0000000000..95479d1b65
--- /dev/null
+++ b/config/method_config.go
@@ -0,0 +1,38 @@
+/*
+ * 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 (
+ "github.com/apache/dubbo-go/common/constant"
+)
+
+type MethodConfig struct {
+ InterfaceId string
+ InterfaceName string
+ Name string `yaml:"name" json:"name,omitempty" property:"name"`
+ Retries int64 `yaml:"retries" json:"retries,omitempty" property:"retries"`
+ Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
+ Weight int64 `yaml:"weight" json:"weight,omitempty" property:"weight"`
+}
+
+func (c *MethodConfig) Prefix() string {
+ if c.InterfaceId != "" {
+ return constant.DUBBO + "." + c.InterfaceName + "." + c.InterfaceId + "." + c.Name + "."
+ } else {
+ return constant.DUBBO + "." + c.InterfaceName + "." + c.Name + "."
+ }
+}
diff --git a/config/protocol_config.go b/config/protocol_config.go
new file mode 100644
index 0000000000..6440f3090d
--- /dev/null
+++ b/config/protocol_config.go
@@ -0,0 +1,47 @@
+/*
+ * 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 (
+ "strings"
+)
+import (
+ "github.com/apache/dubbo-go/common/constant"
+)
+
+type ProtocolConfig struct {
+ Name string `required:"true" yaml:"name" json:"name,omitempty" property:"name"`
+ Ip string `required:"true" yaml:"ip" json:"ip,omitempty" property:"ip"`
+ Port string `required:"true" yaml:"port" json:"port,omitempty" property:"port"`
+}
+
+func (c *ProtocolConfig) Prefix() string {
+ return constant.ProtocolConfigPrefix
+}
+
+func loadProtocol(protocolsIds string, protocols map[string]*ProtocolConfig) []*ProtocolConfig {
+ returnProtocols := []*ProtocolConfig{}
+ for _, v := range strings.Split(protocolsIds, ",") {
+ for _, prot := range protocols {
+ if v == prot.Name {
+ returnProtocols = append(returnProtocols, prot)
+ }
+ }
+
+ }
+ return returnProtocols
+}
diff --git a/config/provider_config.go b/config/provider_config.go
new file mode 100644
index 0000000000..fc7a4d50d2
--- /dev/null
+++ b/config/provider_config.go
@@ -0,0 +1,108 @@
+/*
+ * 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 (
+ "context"
+ "io/ioutil"
+ "path"
+)
+
+import (
+ perrors "github.com/pkg/errors"
+ "gopkg.in/yaml.v2"
+)
+
+import (
+ "github.com/apache/dubbo-go/common/constant"
+ "github.com/apache/dubbo-go/common/logger"
+)
+
+/////////////////////////
+// providerConfig
+/////////////////////////
+
+type ProviderConfig struct {
+ BaseConfig `yaml:",inline"`
+ Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+ ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
+
+ ApplicationConfig *ApplicationConfig `yaml:"application_config" json:"application_config,omitempty" property:"application_config"`
+ Registries map[string]*RegistryConfig `yaml:"registries" json:"registries,omitempty" property:"registries"`
+ Services map[string]*ServiceConfig `yaml:"services" json:"services,omitempty" property:"services"`
+ Protocols map[string]*ProtocolConfig `yaml:"protocols" json:"protocols,omitempty" property:"protocols"`
+ ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf" `
+}
+
+func (*ProviderConfig) Prefix() string {
+ return constant.ProviderConfigPrefix
+}
+
+func SetProviderConfig(p ProviderConfig) {
+ providerConfig = &p
+}
+func GetProviderConfig() ProviderConfig {
+ if providerConfig == nil {
+ logger.Warnf("providerConfig is nil!")
+ return ProviderConfig{}
+ }
+ return *providerConfig
+}
+
+func providerInit(confProFile string) error {
+ if len(confProFile) == 0 {
+ return perrors.Errorf("application configure(provider) file name is nil")
+ }
+
+ if path.Ext(confProFile) != ".yml" {
+ return perrors.Errorf("application configure file name{%v} suffix must be .yml", confProFile)
+ }
+
+ confFileStream, err := ioutil.ReadFile(confProFile)
+ if err != nil {
+ return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confProFile, perrors.WithStack(err))
+ }
+ providerConfig = &ProviderConfig{}
+ err = yaml.Unmarshal(confFileStream, providerConfig)
+ if err != nil {
+ return perrors.Errorf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
+ }
+
+ //set method interfaceId & interfaceName
+ for k, v := range providerConfig.Services {
+ //set id for reference
+ for _, n := range providerConfig.Services[k].Methods {
+ n.InterfaceName = v.InterfaceName
+ n.InterfaceId = k
+ }
+ }
+
+ logger.Debugf("provider config{%#v}\n", providerConfig)
+ return nil
+}
+
+func configCenterRefreshProvider() error {
+ //fresh it
+ if providerConfig.ConfigCenterConfig != nil {
+ providerConfig.fatherConfig = providerConfig
+ if err := providerConfig.startConfigCenter(context.Background()); err != nil {
+ return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
+ }
+ providerConfig.fresh()
+ }
+ return nil
+}
diff --git a/config/reference_config.go b/config/reference_config.go
index ffac5b4267..cd24b769a9 100644
--- a/config/reference_config.go
+++ b/config/reference_config.go
@@ -38,25 +38,25 @@ import (
type ReferenceConfig struct {
context context.Context
pxy *proxy.Proxy
- InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty"`
- Check *bool `yaml:"check" json:"check,omitempty"`
- Url string `yaml:"url" json:"url,omitempty"`
- Filter string `yaml:"filter" json:"filter,omitempty"`
- Protocol string `yaml:"protocol" json:"protocol,omitempty"`
- Registries []ConfigRegistry `required:"true" yaml:"registries" json:"registries,omitempty"`
- Cluster string `yaml:"cluster" json:"cluster,omitempty"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
- Group string `yaml:"group" json:"group,omitempty"`
- Version string `yaml:"version" json:"version,omitempty"`
- Methods []struct {
- Name string `yaml:"name" json:"name,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty"`
- } `yaml:"methods" json:"methods,omitempty"`
- async bool `yaml:"async" json:"async,omitempty"`
- invoker protocol.Invoker
- urls []*common.URL
+ 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"`
+ Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+ Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
+ //Registries []ConfigRegistry `required:"true" yaml:"registries" json:"registries,omitempty" property:"registries"`
+ Cluster string `yaml:"cluster" json:"cluster,omitempty" property:"cluster"`
+ Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
+ Retries int64 `yaml:"retries" json:"retries,omitempty" property:"retries"`
+ Group string `yaml:"group" json:"group,omitempty" property:"group"`
+ Version string `yaml:"version" json:"version,omitempty" property:"version"`
+ Methods []*MethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
+ async bool `yaml:"async" json:"async,omitempty" property:"async"`
+ invoker protocol.Invoker
+ urls []*common.URL
+}
+
+func (c *ReferenceConfig) Prefix() string {
+ return constant.ReferenceConfigPrefix + c.InterfaceName + "."
}
type ConfigRegistry string
@@ -102,7 +102,7 @@ func (refconfig *ReferenceConfig) Refer() {
}
} else {
//2. assemble SubURL from register center's configuration模式
- refconfig.urls = loadRegistries(refconfig.Registries, consumerConfig.Registries, common.CONSUMER)
+ refconfig.urls = loadRegistries(consumerConfig.Registries, common.CONSUMER)
//set url to regUrls
for _, regUrl := range refconfig.urls {
diff --git a/config/reference_config_test.go b/config/reference_config_test.go
index fc58360563..16b23c86d7 100644
--- a/config/reference_config_test.go
+++ b/config/reference_config_test.go
@@ -37,44 +37,40 @@ var regProtocol protocol.Protocol
func doInit() {
consumerConfig = &ConsumerConfig{
- ApplicationConfig: ApplicationConfig{
+ ApplicationConfig: &ApplicationConfig{
Organization: "dubbo_org",
Name: "dubbo",
Module: "module",
Version: "2.6.0",
Owner: "dubbo",
Environment: "test"},
- Registries: []RegistryConfig{
- {
- Id: "shanghai_reg1",
- Type: "mock",
+ Registries: map[string]*RegistryConfig{
+ "shanghai_reg1": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "shanghai_idc",
Address: "127.0.0.1:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "shanghai_reg2",
- Type: "mock",
+ "shanghai_reg2": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "shanghai_idc",
Address: "127.0.0.2:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "hangzhou_reg1",
- Type: "mock",
+ "hangzhou_reg1": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "hangzhou_idc",
Address: "127.0.0.3:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "hangzhou_reg2",
- Type: "mock",
+ "hangzhou_reg2": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "hangzhou_idc",
Address: "127.0.0.4:2181",
@@ -82,21 +78,16 @@ func doInit() {
Password: "pwd1",
},
},
- References: []ReferenceConfig{
- {
+ References: map[string]*ReferenceConfig{
+ "MockService": {
InterfaceName: "MockService",
Protocol: "mock",
- Registries: []ConfigRegistry{"shanghai_reg1", "shanghai_reg2", "hangzhou_reg1", "hangzhou_reg2"},
Cluster: "failover",
Loadbalance: "random",
Retries: 3,
Group: "huadong_idc",
Version: "1.0.0",
- Methods: []struct {
- Name string `yaml:"name" json:"name,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty"`
- }{
+ Methods: []*MethodConfig{
{
Name: "GetUser",
Retries: 2,
@@ -130,7 +121,6 @@ func Test_Refer(t *testing.T) {
doInit()
extension.SetProtocol("registry", GetProtocol)
extension.SetCluster("registryAware", cluster_impl.NewRegistryAwareCluster)
- consumerConfig.References[0].Registries = []ConfigRegistry{"shanghai_reg1"}
for _, reference := range consumerConfig.References {
reference.Refer()
@@ -142,7 +132,8 @@ func Test_Refer(t *testing.T) {
func Test_ReferP2P(t *testing.T) {
doInit()
extension.SetProtocol("dubbo", GetProtocol)
- consumerConfig.References[0].Url = "dubbo://127.0.0.1:20000"
+ m := consumerConfig.References["MockService"]
+ m.Url = "dubbo://127.0.0.1:20000"
for _, reference := range consumerConfig.References {
reference.Refer()
@@ -154,7 +145,8 @@ func Test_ReferP2P(t *testing.T) {
func Test_ReferMultiP2P(t *testing.T) {
doInit()
extension.SetProtocol("dubbo", GetProtocol)
- consumerConfig.References[0].Url = "dubbo://127.0.0.1:20000;dubbo://127.0.0.2:20000"
+ m := consumerConfig.References["MockService"]
+ m.Url = "dubbo://127.0.0.1:20000;dubbo://127.0.0.2:20000"
for _, reference := range consumerConfig.References {
reference.Refer()
@@ -168,7 +160,8 @@ func Test_ReferMultiP2PWithReg(t *testing.T) {
doInit()
extension.SetProtocol("dubbo", GetProtocol)
extension.SetProtocol("registry", GetProtocol)
- consumerConfig.References[0].Url = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
+ 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()
diff --git a/config/registry_config.go b/config/registry_config.go
index 6dcf5bde75..8d6b1dc2b4 100644
--- a/config/registry_config.go
+++ b/config/registry_config.go
@@ -30,40 +30,40 @@ import (
)
type RegistryConfig struct {
- Id string `required:"true" yaml:"id" json:"id,omitempty"`
- Type string `required:"true" yaml:"type" json:"type,omitempty"`
- TimeoutStr string `yaml:"timeout" default:"5s" json:"timeout,omitempty"` // unit: second
- Group string `yaml:"group" json:"group,omitempty"`
+ Protocol string `required:"true" yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
+ //I changed "type" to "protocol" ,the same as "protocol" field in java class RegistryConfig
+ 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"`
- Username string `yaml:"username" json:"address,omitempty"`
- Password string `yaml:"password" json:"address,omitempty"`
+ Address string `yaml:"address" json:"address,omitempty" property:"address"`
+ Username string `yaml:"username" json:"address,omitempty" property:"username"`
+ Password string `yaml:"password" json:"address,omitempty" property:"password"`
}
-func loadRegistries(registriesIds []ConfigRegistry, registries []RegistryConfig, roleType common.RoleType) []*common.URL {
- var urls []*common.URL
- for _, registry := range registriesIds {
- for _, registryConf := range registries {
- if string(registry) == registryConf.Id {
+func (*RegistryConfig) Prefix() string {
+ return constant.RegistryConfigPrefix
+}
- url, err := common.NewURL(
- context.TODO(),
- constant.REGISTRY_PROTOCOL+"://"+registryConf.Address,
- common.WithParams(registryConf.getUrlMap(roleType)),
- common.WithUsername(registryConf.Username),
- common.WithPassword(registryConf.Password),
- )
+func loadRegistries(registries map[string]*RegistryConfig, roleType common.RoleType) []*common.URL {
+ var urls []*common.URL
+ for k, registryConf := range registries {
- if err != nil {
- logger.Errorf("The registry id:%s url is invalid ,and will skip the registry, error: %#v", registryConf.Id, err)
- } else {
- urls = append(urls, &url)
- }
+ url, err := common.NewURL(
+ context.TODO(),
+ 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)
+ } else {
+ urls = append(urls, &url)
}
}
+
return urls
}
@@ -71,7 +71,7 @@ func (regconfig *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values
urlMap := url.Values{}
urlMap.Set(constant.GROUP_KEY, regconfig.Group)
urlMap.Set(constant.ROLE_KEY, strconv.Itoa(int(roleType)))
- urlMap.Set(constant.REGISTRY_KEY, regconfig.Type)
+ urlMap.Set(constant.REGISTRY_KEY, regconfig.Protocol)
urlMap.Set(constant.REGISTRY_TIMEOUT_KEY, regconfig.TimeoutStr)
return urlMap
diff --git a/config/service_config.go b/config/service_config.go
index e225c95423..73a0cc39b9 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -43,22 +43,17 @@ import (
type ServiceConfig struct {
context context.Context
- Filter string `yaml:"filter" json:"filter,omitempty"`
- Protocol string `required:"true" yaml:"protocol" json:"protocol,omitempty"` //multi protocol support, split by ','
- InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty"`
- Registries []ConfigRegistry `required:"true" yaml:"registries" json:"registries,omitempty"`
- Cluster string `default:"failover" yaml:"cluster" json:"cluster,omitempty"`
- Loadbalance string `default:"random" yaml:"loadbalance" json:"loadbalance,omitempty"`
- Group string `yaml:"group" json:"group,omitempty"`
- Version string `yaml:"version" json:"version,omitempty"`
- Methods []struct {
- Name string `yaml:"name" json:"name,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty"`
- Weight int64 `yaml:"weight" json:"weight,omitempty"`
- } `yaml:"methods" json:"methods,omitempty"`
- Warmup string `yaml:"warmup" json:"warmup,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
+ 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"`
+ Registries []ConfigRegistry `required:"true" yaml:"registries" json:"registries,omitempty" property:"registries"`
+ Cluster string `default:"failover" yaml:"cluster" json:"cluster,omitempty" property:"cluster"`
+ Loadbalance string `default:"random" yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
+ Group string `yaml:"group" json:"group,omitempty" property:"group"`
+ Version string `yaml:"version" json:"version,omitempty" property:"version" `
+ Methods []*MethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
+ Warmup string `yaml:"warmup" json:"warmup,omitempty" property:"warmup"`
+ Retries int64 `yaml:"retries" json:"retries,omitempty" property:"retries"`
unexported *atomic.Bool
exported *atomic.Bool
rpcService common.RPCService
@@ -67,6 +62,10 @@ type ServiceConfig struct {
cacheMutex sync.Mutex
}
+func (c *ServiceConfig) Prefix() string {
+ return constant.ServiceConfigPrefix + c.InterfaceName + "."
+}
+
func NewServiceConfig() *ServiceConfig {
return &ServiceConfig{
unexported: atomic.NewBool(false),
@@ -89,7 +88,7 @@ func (srvconfig *ServiceConfig) Export() error {
return nil
}
- regUrls := loadRegistries(srvconfig.Registries, providerConfig.Registries, common.PROVIDER)
+ regUrls := loadRegistries(providerConfig.Registries, common.PROVIDER)
urlMap := srvconfig.getUrlMap()
for _, proto := range loadProtocol(srvconfig.Protocol, providerConfig.Protocols) {
diff --git a/config/service_config_test.go b/config/service_config_test.go
index 99835f6306..5107dea211 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -31,44 +31,40 @@ import (
func doinit() {
providerConfig = &ProviderConfig{
- ApplicationConfig: ApplicationConfig{
+ ApplicationConfig: &ApplicationConfig{
Organization: "dubbo_org",
Name: "dubbo",
Module: "module",
Version: "2.6.0",
Owner: "dubbo",
Environment: "test"},
- Registries: []RegistryConfig{
- {
- Id: "shanghai_reg1",
- Type: "mock",
+ Registries: map[string]*RegistryConfig{
+ "shanghai_reg1": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "shanghai_idc",
Address: "127.0.0.1:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "shanghai_reg2",
- Type: "mock",
+ "shanghai_reg2": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "shanghai_idc",
Address: "127.0.0.2:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "hangzhou_reg1",
- Type: "mock",
+ "hangzhou_reg1": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "hangzhou_idc",
Address: "127.0.0.3:2181",
Username: "user1",
Password: "pwd1",
},
- {
- Id: "hangzhou_reg2",
- Type: "mock",
+ "hangzhou_reg2": {
+ Protocol: "mock",
TimeoutStr: "2s",
Group: "hangzhou_idc",
Address: "127.0.0.4:2181",
@@ -76,8 +72,8 @@ func doinit() {
Password: "pwd1",
},
},
- Services: []ServiceConfig{
- {
+ Services: map[string]*ServiceConfig{
+ "MockService": {
InterfaceName: "MockService",
Protocol: "mock",
Registries: []ConfigRegistry{"shanghai_reg1", "shanghai_reg2", "hangzhou_reg1", "hangzhou_reg2"},
@@ -86,12 +82,7 @@ func doinit() {
Retries: 3,
Group: "huadong_idc",
Version: "1.0.0",
- Methods: []struct {
- Name string `yaml:"name" json:"name,omitempty"`
- Retries int64 `yaml:"retries" json:"retries,omitempty"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty"`
- Weight int64 `yaml:"weight" json:"weight,omitempty"`
- }{
+ Methods: []*MethodConfig{
{
Name: "GetUser",
Retries: 2,
@@ -107,12 +98,11 @@ func doinit() {
},
},
},
- Protocols: []ProtocolConfig{
- {
- Name: "mock",
- Ip: "127.0.0.1",
- Port: "20000",
- ContextPath: "/xxx",
+ Protocols: map[string]*ProtocolConfig{
+ "mock": {
+ Name: "mock",
+ Ip: "127.0.0.1",
+ Port: "20000",
},
},
}
@@ -122,7 +112,7 @@ func Test_Export(t *testing.T) {
doinit()
extension.SetProtocol("registry", GetProtocol)
- for i := 0; i < len(providerConfig.Services); i++ {
+ for i := range providerConfig.Services {
service := providerConfig.Services[i]
service.Implement(&MockService{})
service.Export()
diff --git a/config/testdata/consumer_config.yml b/config/testdata/consumer_config.yml
index 9095c44d4f..2d8287853b 100644
--- a/config/testdata/consumer_config.yml
+++ b/config/testdata/consumer_config.yml
@@ -17,14 +17,16 @@ application_config:
environment : "dev"
registries :
- - id: "hangzhouzk"
+
+ "hangzhouzk":
+ id: "hangzhouzk"
type: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
+ "shanghaizk":
+ id: "shanghaizk"
type: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
@@ -32,9 +34,7 @@ registries :
password: ""
references:
- - registries :
- - "hangzhouzk"
- - "shanghaizk"
+ "UserProvider":
filter: ""
protocol : "dubbo"
interface : "com.ikurento.user.UserProvider"
diff --git a/config/testdata/consumer_config_with_configcenter.yml b/config/testdata/consumer_config_with_configcenter.yml
new file mode 100644
index 0000000000..acaed2ade2
--- /dev/null
+++ b/config/testdata/consumer_config_with_configcenter.yml
@@ -0,0 +1,39 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "mock"
+ address: "127.0.0.1"
+references:
+ "UserProvider":
+ filter: ""
+ protocol : "dubbo"
+ interface : "com.ikurento.user.UserProvider"
+ url: "dubbo://127.0.0.1:20000"
+ 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: 1024
+ session_name: "client"
diff --git a/config/testdata/provider_config.yml b/config/testdata/provider_config.yml
index b02384798f..56d658e954 100644
--- a/config/testdata/provider_config.yml
+++ b/config/testdata/provider_config.yml
@@ -11,14 +11,13 @@ application_config:
environment : "dev"
registries :
- - id: "hangzhouzk"
+ "hangzhouzk":
type: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
+ "shanghaizk":
type: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
@@ -27,9 +26,7 @@ registries :
services:
- - registries:
- - "hangzhouzk"
- - "shanghaizk"
+ "UserProvider":
filter: ""
protocol : "dubbo"
# equivalent to interface of dubbo.xml
@@ -43,7 +40,8 @@ services:
loadbalance: "random"
protocols:
- - name: "dubbo"
+ "dubbo":
+ name: "dubbo"
# while using dubbo protocol, ip cannot is 127.0.0.1, because client of java-dubbo will get 'connection refuse'
ip : "127.0.0.1"
port : 20000
diff --git a/config_center/configuration_parser.go b/config_center/configuration_parser.go
new file mode 100644
index 0000000000..ab02789c92
--- /dev/null
+++ b/config_center/configuration_parser.go
@@ -0,0 +1,24 @@
+package config_center
+
+import (
+ "github.com/magiconair/properties"
+)
+import (
+ "github.com/apache/dubbo-go/common/logger"
+)
+
+type ConfigurationParser interface {
+ Parse(string) (map[string]string, error)
+}
+
+//for support properties file in config center
+type DefaultConfigurationParser struct{}
+
+func (parser *DefaultConfigurationParser) Parse(content string) (map[string]string, error) {
+ properties, err := properties.LoadString(content)
+ if err != nil {
+ logger.Errorf("Parse the content {%v} in DefaultConfigurationParser error ,error message is {%v}", content, err)
+ return nil, err
+ }
+ return properties.Map(), nil
+}
diff --git a/config_center/configuration_parser_test.go b/config_center/configuration_parser_test.go
new file mode 100644
index 0000000000..3c84fd70b0
--- /dev/null
+++ b/config_center/configuration_parser_test.go
@@ -0,0 +1,16 @@
+package config_center
+
+import (
+ "testing"
+)
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+func TestDefaultConfigurationParser_Parser(t *testing.T) {
+ parser := &DefaultConfigurationParser{}
+ m, err := parser.Parse("dubbo.registry.address=172.0.0.1\ndubbo.registry.name=test")
+ assert.NoError(t, err)
+ assert.Equal(t, 2, len(m))
+ assert.Equal(t, "172.0.0.1", m["dubbo.registry.address"])
+}
diff --git a/config_center/dynamic_configuration.go b/config_center/dynamic_configuration.go
index 8115fed820..3b829507b1 100644
--- a/config_center/dynamic_configuration.go
+++ b/config_center/dynamic_configuration.go
@@ -31,10 +31,12 @@ const DEFAULT_GROUP = "dubbo"
const DEFAULT_CONFIG_TIMEOUT = "10s"
type DynamicConfiguration interface {
+ Parser() ConfigurationParser
+ SetParser(ConfigurationParser)
AddListener(string, remoting.ConfigurationListener, ...Option)
RemoveListener(string, remoting.ConfigurationListener, ...Option)
- GetConfig(string, ...Option) string
- GetConfigs(string, ...Option) string
+ GetConfig(string, ...Option) (string, error)
+ GetConfigs(string, ...Option) (string, error)
}
type Options struct {
diff --git a/config_center/dynamic_configuration_factory.go b/config_center/dynamic_configuration_factory.go
new file mode 100644
index 0000000000..0720896fb6
--- /dev/null
+++ b/config_center/dynamic_configuration_factory.go
@@ -0,0 +1,26 @@
+/*
+ * 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_center
+
+import (
+ "github.com/apache/dubbo-go/common"
+)
+
+type DynamicConfigurationFactory interface {
+ GetDynamicConfiguration(*common.URL) (DynamicConfiguration, error)
+}
diff --git a/config_center/mock_dynamic_config.go b/config_center/mock_dynamic_config.go
new file mode 100644
index 0000000000..a6c7267a4f
--- /dev/null
+++ b/config_center/mock_dynamic_config.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 config_center
+
+import (
+ "sync"
+)
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/remoting"
+)
+
+type MockDynamicConfigurationFactory struct{}
+
+var (
+ once sync.Once
+ dynamicConfiguration *mockDynamicConfiguration
+)
+
+func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(url *common.URL) (DynamicConfiguration, error) {
+ var err error
+ once.Do(func() {
+ dynamicConfiguration = &mockDynamicConfiguration{}
+ dynamicConfiguration.SetParser(&DefaultConfigurationParser{})
+ dynamicConfiguration.content = `
+ dubbo.consumer.request_timeout=5s
+ 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
+ dubbo.protocols.jsonrpc1.name=jsonrpc
+ dubbo.protocols.jsonrpc1.ip=127.0.0.1
+ dubbo.protocols.jsonrpc1.port=20001
+`
+ })
+ return dynamicConfiguration, err
+
+}
+
+type mockDynamicConfiguration struct {
+ parser ConfigurationParser
+ content string
+}
+
+func (c *mockDynamicConfiguration) AddListener(key string, listener remoting.ConfigurationListener, opions ...Option) {
+}
+
+func (c *mockDynamicConfiguration) RemoveListener(key string, listener remoting.ConfigurationListener, opions ...Option) {
+}
+
+func (c *mockDynamicConfiguration) GetConfig(key string, opts ...Option) (string, error) {
+
+ return c.content, nil
+}
+
+//For zookeeper, getConfig and getConfigs have the same meaning.
+func (c *mockDynamicConfiguration) GetConfigs(key string, opts ...Option) (string, error) {
+ return c.GetConfig(key, opts...)
+}
+
+func (c *mockDynamicConfiguration) Parser() ConfigurationParser {
+ return c.parser
+}
+func (c *mockDynamicConfiguration) SetParser(p ConfigurationParser) {
+ c.parser = p
+}
diff --git a/config_center/zookeeper/dynamic_configuration.go b/config_center/zookeeper/dynamic_configuration.go
deleted file mode 100644
index c998c586fb..0000000000
--- a/config_center/zookeeper/dynamic_configuration.go
+++ /dev/null
@@ -1,134 +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 zookeeper
-
-import (
- "sync"
-)
-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/config_center"
- "github.com/apache/dubbo-go/remoting"
- "github.com/apache/dubbo-go/remoting/zookeeper"
-)
-
-const ZK_CLIENT = "zk config_center"
-
-type ZookeeperDynamicConfiguration struct {
- url common.URL
- rootPath string
- wg sync.WaitGroup
- cltLock sync.Mutex
- done chan struct{}
- client *zookeeper.ZookeeperClient
-
- listenerLock sync.Mutex
- listener *zookeeper.ZkEventListener
-}
-
-func NewZookeeperDynamicConfiguration(url common.URL) (config_center.DynamicConfiguration, error) {
- c := &ZookeeperDynamicConfiguration{
- url: url,
- rootPath: "/" + url.GetParam(constant.CONFIG_NAMESPACE_KEY, config_center.DEFAULT_GROUP) + "/config",
- }
- err := zookeeper.ValidateZookeeperClient(c, zookeeper.WithZkName(ZK_CLIENT))
- if err != nil {
- return nil, err
- }
- c.wg.Add(1)
- go zookeeper.HandleClientRestart(c)
-
- c.listener = zookeeper.NewZkEventListener(c.client)
- //c.configListener = NewRegistryConfigurationListener(c.client, c)
- //c.dataListener = NewRegistryDataListener(c.configListener)
- return c, nil
-
-}
-
-func (*ZookeeperDynamicConfiguration) AddListener(key string, listener remoting.ConfigurationListener, opions ...config_center.Option) {
-
-}
-
-func (*ZookeeperDynamicConfiguration) RemoveListener(key string, listener remoting.ConfigurationListener, opions ...config_center.Option) {
-
-}
-
-func (*ZookeeperDynamicConfiguration) GetConfig(key string, opions ...config_center.Option) string {
- return ""
-}
-
-func (*ZookeeperDynamicConfiguration) GetConfigs(key string, opions ...config_center.Option) string {
- return ""
-}
-
-func (r *ZookeeperDynamicConfiguration) ZkClient() *zookeeper.ZookeeperClient {
- return r.client
-}
-
-func (r *ZookeeperDynamicConfiguration) SetZkClient(client *zookeeper.ZookeeperClient) {
- r.client = client
-}
-
-func (r *ZookeeperDynamicConfiguration) ZkClientLock() *sync.Mutex {
- return &r.cltLock
-}
-
-func (r *ZookeeperDynamicConfiguration) WaitGroup() *sync.WaitGroup {
- return &r.wg
-}
-
-func (r *ZookeeperDynamicConfiguration) GetDone() chan struct{} {
- return r.done
-}
-
-func (r *ZookeeperDynamicConfiguration) GetUrl() common.URL {
- return r.url
-}
-
-func (r *ZookeeperDynamicConfiguration) Destroy() {
- if r.listener != nil {
- r.listener.Close()
- }
- close(r.done)
- r.wg.Wait()
- r.closeConfigs()
-}
-
-func (r *ZookeeperDynamicConfiguration) IsAvailable() bool {
- select {
- case <-r.done:
- return false
- default:
- return true
- }
-}
-
-func (r *ZookeeperDynamicConfiguration) closeConfigs() {
- r.cltLock.Lock()
- defer r.cltLock.Unlock()
- logger.Infof("begin to close provider zk client")
- // 先关闭旧client,以关闭tmp node
- r.client.Close()
- r.client = nil
-}
-
-func (r *ZookeeperDynamicConfiguration) RestartCallBack() bool {
- return true
-}
diff --git a/config_center/zookeeper/factory.go b/config_center/zookeeper/factory.go
new file mode 100644
index 0000000000..c1c7e27b14
--- /dev/null
+++ b/config_center/zookeeper/factory.go
@@ -0,0 +1,50 @@
+/*
+ * 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 zookeeper
+
+import (
+ "sync"
+)
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/config_center"
+)
+
+func init() {
+ extension.SetConfigCenterFactory("zookeeper", func() config_center.DynamicConfigurationFactory { return &zookeeperDynamicConfigurationFactory{} })
+}
+
+type zookeeperDynamicConfigurationFactory struct {
+}
+
+var once sync.Once
+var dynamicConfiguration *zookeeperDynamicConfiguration
+
+func (f *zookeeperDynamicConfigurationFactory) GetDynamicConfiguration(url *common.URL) (config_center.DynamicConfiguration, error) {
+ var err error
+ once.Do(func() {
+ dynamicConfiguration, err = newZookeeperDynamicConfiguration(url)
+ })
+ if err != nil {
+ return nil, err
+ }
+ dynamicConfiguration.SetParser(&config_center.DefaultConfigurationParser{})
+ return dynamicConfiguration, err
+
+}
diff --git a/config_center/zookeeper/impl.go b/config_center/zookeeper/impl.go
new file mode 100644
index 0000000000..6b526b0c67
--- /dev/null
+++ b/config_center/zookeeper/impl.go
@@ -0,0 +1,206 @@
+/*
+ * 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 zookeeper
+
+import (
+ "strings"
+ "sync"
+ "time"
+)
+import (
+ perrors "github.com/pkg/errors"
+ "github.com/samuel/go-zookeeper/zk"
+)
+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/config_center"
+ "github.com/apache/dubbo-go/remoting"
+ "github.com/apache/dubbo-go/remoting/zookeeper"
+)
+
+const ZkClient = "zk config_center"
+
+type zookeeperDynamicConfiguration struct {
+ url *common.URL
+ rootPath string
+ wg sync.WaitGroup
+ cltLock sync.Mutex
+ done chan struct{}
+ client *zookeeper.ZookeeperClient
+
+ listenerLock sync.Mutex
+ listener *zookeeper.ZkEventListener
+ cacheListener *CacheListener
+ parser config_center.ConfigurationParser
+}
+
+func newZookeeperDynamicConfiguration(url *common.URL) (*zookeeperDynamicConfiguration, error) {
+ c := &zookeeperDynamicConfiguration{
+ url: url,
+ rootPath: "/" + url.GetParam(constant.CONFIG_NAMESPACE_KEY, config_center.DEFAULT_GROUP) + "/config",
+ }
+ err := zookeeper.ValidateZookeeperClient(c, zookeeper.WithZkName(ZkClient))
+ if err != nil {
+ logger.Errorf("zookeeper client start error ,error message is %v", err)
+ return nil, err
+ }
+ c.wg.Add(1)
+ go zookeeper.HandleClientRestart(c)
+
+ c.listener = zookeeper.NewZkEventListener(c.client)
+ c.cacheListener = NewCacheListener(c.rootPath)
+
+ err = c.client.Create(c.rootPath)
+ c.listener.ListenServiceEvent(c.rootPath, c.cacheListener)
+ return c, nil
+
+}
+
+func newMockZookeeperDynamicConfiguration(url *common.URL, opts ...zookeeper.Option) (*zk.TestCluster, *zookeeperDynamicConfiguration, error) {
+ c := &zookeeperDynamicConfiguration{
+ url: url,
+ rootPath: "/" + url.GetParam(constant.CONFIG_NAMESPACE_KEY, config_center.DEFAULT_GROUP) + "/config",
+ }
+ var (
+ tc *zk.TestCluster
+ err error
+ )
+ tc, c.client, _, err = zookeeper.NewMockZookeeperClient("test", 15*time.Second, opts...)
+ if err != nil {
+ logger.Errorf("mock zookeeper client start error ,error message is %v", err)
+ return tc, c, err
+ }
+ c.wg.Add(1)
+ go zookeeper.HandleClientRestart(c)
+
+ c.listener = zookeeper.NewZkEventListener(c.client)
+ c.cacheListener = NewCacheListener(c.rootPath)
+
+ err = c.client.Create(c.rootPath)
+ go c.listener.ListenServiceEvent(c.rootPath, c.cacheListener)
+ return tc, c, nil
+
+}
+
+func (c *zookeeperDynamicConfiguration) AddListener(key string, listener remoting.ConfigurationListener, opions ...config_center.Option) {
+ c.cacheListener.AddListener(key, listener)
+}
+
+func (c *zookeeperDynamicConfiguration) RemoveListener(key string, listener remoting.ConfigurationListener, opions ...config_center.Option) {
+ c.cacheListener.RemoveListener(key, listener)
+}
+
+func (c *zookeeperDynamicConfiguration) GetConfig(key string, opts ...config_center.Option) (string, error) {
+
+ tmpOpts := &config_center.Options{}
+ for _, opt := range opts {
+ opt(tmpOpts)
+ }
+ /**
+ * when group is not null, we are getting startup configs from Config Center, for example:
+ * group=dubbo, key=dubbo.properties
+ */
+ if len(tmpOpts.Group) != 0 {
+ key = tmpOpts.Group + "/" + key
+ } else {
+
+ /**
+ * when group is null, we are fetching governance rules, for example:
+ * 1. key=org.apache.dubbo.DemoService.configurators
+ * 2. key = org.apache.dubbo.DemoService.condition-router
+ */
+ i := strings.LastIndex(key, ".")
+ key = key[0:i] + "/" + key[i+1:]
+ }
+ content, _, err := c.client.GetContent(c.rootPath + "/" + key)
+ if err != nil {
+ return "", perrors.WithStack(err)
+ } else {
+ return string(content), nil
+ }
+
+}
+
+//For zookeeper, getConfig and getConfigs have the same meaning.
+func (c *zookeeperDynamicConfiguration) GetConfigs(key string, opts ...config_center.Option) (string, error) {
+ return c.GetConfig(key, opts...)
+}
+
+func (c *zookeeperDynamicConfiguration) Parser() config_center.ConfigurationParser {
+ return c.parser
+}
+func (c *zookeeperDynamicConfiguration) SetParser(p config_center.ConfigurationParser) {
+ c.parser = p
+}
+
+func (r *zookeeperDynamicConfiguration) ZkClient() *zookeeper.ZookeeperClient {
+ return r.client
+}
+
+func (r *zookeeperDynamicConfiguration) SetZkClient(client *zookeeper.ZookeeperClient) {
+ r.client = client
+}
+
+func (r *zookeeperDynamicConfiguration) ZkClientLock() *sync.Mutex {
+ return &r.cltLock
+}
+
+func (r *zookeeperDynamicConfiguration) WaitGroup() *sync.WaitGroup {
+ return &r.wg
+}
+
+func (r *zookeeperDynamicConfiguration) GetDone() chan struct{} {
+ return r.done
+}
+
+func (r *zookeeperDynamicConfiguration) GetUrl() common.URL {
+ return *r.url
+}
+
+func (r *zookeeperDynamicConfiguration) Destroy() {
+ if r.listener != nil {
+ r.listener.Close()
+ }
+ close(r.done)
+ r.wg.Wait()
+ r.closeConfigs()
+}
+
+func (r *zookeeperDynamicConfiguration) IsAvailable() bool {
+ select {
+ case <-r.done:
+ return false
+ default:
+ return true
+ }
+}
+
+func (r *zookeeperDynamicConfiguration) closeConfigs() {
+ r.cltLock.Lock()
+ defer r.cltLock.Unlock()
+ logger.Infof("begin to close provider zk client")
+ // 先关闭旧client,以关闭tmp node
+ r.client.Close()
+ r.client = nil
+}
+
+func (r *zookeeperDynamicConfiguration) RestartCallBack() bool {
+ return true
+}
diff --git a/config_center/zookeeper/impl_test.go b/config_center/zookeeper/impl_test.go
new file mode 100644
index 0000000000..26b899e82d
--- /dev/null
+++ b/config_center/zookeeper/impl_test.go
@@ -0,0 +1,168 @@
+/*
+ * 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 zookeeper
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "testing"
+)
+
+import (
+ "github.com/samuel/go-zookeeper/zk"
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/config_center"
+ "github.com/apache/dubbo-go/remoting"
+)
+
+func initZkData(group string, t *testing.T) (*zk.TestCluster, *zookeeperDynamicConfiguration) {
+ regurl, _ := common.NewURL(context.TODO(), "registry://127.0.0.1:1111")
+ ts, reg, err := newMockZookeeperDynamicConfiguration(®url)
+ reg.SetParser(&config_center.DefaultConfigurationParser{})
+
+ assert.NoError(t, err)
+
+ data := `
+ dubbo.consumer.request_timeout=5s
+ 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
+`
+ if group != "" {
+ err = reg.client.Create(reg.rootPath + "/dubbo/dubbo.properties")
+ assert.NoError(t, err)
+
+ _, err = reg.client.Conn.Set(reg.rootPath+"/dubbo/dubbo.properties", []byte(data), 0)
+ assert.NoError(t, err)
+ } else {
+ err = reg.client.Create(reg.rootPath + "/dubbo.properties")
+ assert.NoError(t, err)
+
+ _, err = reg.client.Conn.Set(reg.rootPath+"/dubbo.properties", []byte(data), 0)
+ assert.NoError(t, err)
+ }
+
+ return ts, reg
+}
+func Test_GetConfig(t *testing.T) {
+ ts, reg := initZkData("dubbo", t)
+ defer ts.Stop()
+ configs, err := reg.GetConfig("dubbo.properties", config_center.WithGroup("dubbo"))
+ assert.NoError(t, err)
+ m, err := reg.Parser().Parse(configs)
+ assert.NoError(t, err)
+ assert.Equal(t, "5s", m["dubbo.consumer.request_timeout"])
+}
+
+func Test_AddListener(t *testing.T) {
+ ts, reg := initZkData("", t)
+ defer ts.Stop()
+ listener := &mockDataListener{}
+ reg.AddListener("dubbo.properties", listener)
+ listener.wg.Add(1)
+ data := `
+ 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
+`
+ _, err := reg.client.Conn.Set(reg.rootPath+"/dubbo.properties", []byte(data), 1)
+ assert.NoError(t, err)
+ listener.wg.Wait()
+ assert.Equal(t, "dubbo.properties", listener.event)
+}
+
+func Test_RemoveListener(t *testing.T) {
+ ts, reg := initZkData("", t)
+ defer ts.Stop()
+ listener := &mockDataListener{}
+ reg.AddListener("dubbo.properties", listener)
+ listener.wg.Add(1)
+ data := `
+ 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
+`
+ reg.RemoveListener("dubbo.properties", listener)
+ listener.wg.Done()
+ _, err := reg.client.Conn.Set(reg.rootPath+"/dubbo.properties", []byte(data), 1)
+ assert.NoError(t, err)
+ listener.wg.Wait()
+ assert.Equal(t, "", listener.event)
+}
+
+type mockDataListener struct {
+ wg sync.WaitGroup
+ event string
+}
+
+func (l *mockDataListener) Process(configType *remoting.ConfigChangeEvent) {
+ fmt.Println("process!!!!!")
+ l.wg.Done()
+ l.event = configType.Key
+}
diff --git a/config_center/zookeeper/listener.go b/config_center/zookeeper/listener.go
new file mode 100644
index 0000000000..c79c05c9bc
--- /dev/null
+++ b/config_center/zookeeper/listener.go
@@ -0,0 +1,73 @@
+/*
+ * 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 zookeeper
+
+import (
+ "strings"
+ "sync"
+)
+import (
+ "github.com/apache/dubbo-go/remoting"
+)
+
+type CacheListener struct {
+ keyListeners sync.Map
+ rootPath string
+}
+
+func NewCacheListener(rootPath string) *CacheListener {
+ return &CacheListener{rootPath: rootPath}
+}
+func (l *CacheListener) AddListener(key string, listener remoting.ConfigurationListener) {
+
+ // reference from https://stackoverflow.com/questions/34018908/golang-why-dont-we-have-a-set-datastructure
+ // make a map[your type]struct{} like set in java
+ listeners, loaded := l.keyListeners.LoadOrStore(key, map[remoting.ConfigurationListener]struct{}{listener: struct{}{}})
+ if loaded {
+ listeners.(map[remoting.ConfigurationListener]struct{})[listener] = struct{}{}
+ l.keyListeners.Store(key, listeners)
+ }
+}
+
+func (l *CacheListener) RemoveListener(key string, listener remoting.ConfigurationListener) {
+ listeners, loaded := l.keyListeners.Load(key)
+ if loaded {
+ delete(listeners.(map[remoting.ConfigurationListener]struct{}), listener)
+ }
+}
+
+func (l *CacheListener) DataChange(event remoting.Event) bool {
+ if event.Content == "" {
+ //meanings new node
+ return true
+ }
+ key := l.pathToKey(event.Path)
+ if key != "" {
+ if listeners, ok := l.keyListeners.Load(key); ok {
+ for listener := range listeners.(map[remoting.ConfigurationListener]struct{}) {
+ listener.Process(&remoting.ConfigChangeEvent{Key: key, Value: event.Content, ConfigType: event.Action})
+ }
+ return true
+ }
+ }
+ return false
+}
+
+func (l *CacheListener) pathToKey(path string) string {
+ return strings.Replace(strings.Replace(path, l.rootPath+"/", "", -1), "/", ".", -1)
+}
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
new file mode 100644
index 0000000000..839531b8b8
Binary files /dev/null and b/config_center/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar differ
diff --git a/examples/dubbo/go-client/app/client.go b/examples/dubbo/go-client/app/client.go
index 8fea06a05b..7918e2df0f 100644
--- a/examples/dubbo/go-client/app/client.go
+++ b/examples/dubbo/go-client/app/client.go
@@ -57,10 +57,7 @@ func main() {
hessian.RegisterJavaEnum(Gender(WOMAN))
hessian.RegisterPOJO(&User{})
- conLen, _ := config.Load()
- if conLen == 0 {
- panic("conMap is nil")
- }
+ config.Load()
println("\n\n\necho")
res, err := userProvider.Echo(context.TODO(), "OK")
diff --git a/examples/dubbo/go-client/profiles/dev/client.yml b/examples/dubbo/go-client/profiles/dev/client.yml
index 2eae902e50..3765305c66 100644
--- a/examples/dubbo/go-client/profiles/dev/client.yml
+++ b/examples/dubbo/go-client/profiles/dev/client.yml
@@ -1,43 +1,39 @@
# dubbo client yaml configure file
+
+check: true
# client
-request_timeout : "100ms"
+request_timeout : "3s"
# connect timeout
-connect_timeout : "100ms"
-check: true
+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 : "dev"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ # 对应java配置中address属性的zookeeper
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "dubbo"
-# version: "2.0"
-# group: "as"
- # url: "dubbo://127.0.0.1:20000"
interface : "com.ikurento.user.UserProvider"
cluster: "failover"
methods :
diff --git a/examples/dubbo/go-client/profiles/release/client.yml b/examples/dubbo/go-client/profiles/release/client.yml
index d30a9907f4..5fb148618e 100644
--- a/examples/dubbo/go-client/profiles/release/client.yml
+++ b/examples/dubbo/go-client/profiles/release/client.yml
@@ -1,10 +1,12 @@
# dubbo client yaml configure file
+
+check: true
# client
-request_timeout : "100ms"
+request_timeout : "3s"
# connect timeout
-connect_timeout : "100ms"
-check: true
+connect_timeout : "3s"
+
# application config
application_config:
organization : "ikurento.com"
@@ -12,28 +14,24 @@ application_config:
module : "dubbogo user-info client"
version : "0.0.1"
owner : "ZX"
- environment : "dev"
+ environment : "release"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "dubbo"
# version: "2.0"
# group: "as"
diff --git a/examples/dubbo/go-client/profiles/test/client.yml b/examples/dubbo/go-client/profiles/test/client.yml
index d30a9907f4..5f09d7302b 100644
--- a/examples/dubbo/go-client/profiles/test/client.yml
+++ b/examples/dubbo/go-client/profiles/test/client.yml
@@ -1,10 +1,12 @@
# dubbo client yaml configure file
+
+check: true
# client
-request_timeout : "100ms"
+request_timeout : "3s"
# connect timeout
-connect_timeout : "100ms"
-check: true
+connect_timeout : "3s"
+
# application config
application_config:
organization : "ikurento.com"
@@ -12,28 +14,24 @@ application_config:
module : "dubbogo user-info client"
version : "0.0.1"
owner : "ZX"
- environment : "dev"
+ environment : "test"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "dubbo"
# version: "2.0"
# group: "as"
diff --git a/examples/dubbo/go-server/app/server.go b/examples/dubbo/go-server/app/server.go
index 2a032a624c..788fc665b8 100644
--- a/examples/dubbo/go-server/app/server.go
+++ b/examples/dubbo/go-server/app/server.go
@@ -58,10 +58,7 @@ func main() {
hessian.RegisterPOJO(&User{})
// ------------
- _, proLen := config.Load()
- if proLen == 0 {
- panic("proMap is nil")
- }
+ config.Load()
initSignal()
}
diff --git a/examples/dubbo/go-server/profiles/dev/server.yml b/examples/dubbo/go-server/profiles/dev/server.yml
index 521f916faa..58dd8a4cd5 100644
--- a/examples/dubbo/go-server/profiles/dev/server.yml
+++ b/examples/dubbo/go-server/profiles/dev/server.yml
@@ -1,24 +1,25 @@
# 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"
+ organization : "ikurento.com"
+ name : "BDTService"
+ module : "dubbogo user-info server"
+ version : "0.0.1"
+ owner : "ZX"
+ environment : "dev"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ # 对应java配置中address属性的zookeeper
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
@@ -26,11 +27,10 @@ registries :
services:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
+
+ "UserProvider":
protocol : "dubbo"
- # 相当于dubbo.xml中的interface
+ # 相当于dubbo.xml中的interface
interface : "com.ikurento.user.UserProvider"
loadbalance: "random"
warmup: "100"
@@ -41,12 +41,11 @@ services:
loadbalance: "random"
protocols:
- - name: "dubbo"
+ "dubbo1":
+ name: "dubbo"
# ip : "127.0.0.1"
- port : 20000
- #- name: "jsonrpc"
- # ip: "127.0.0.1"
- # port: 20001
+ port: 20000
+
protocol_conf:
dubbo:
diff --git a/examples/dubbo/go-server/profiles/release/server.yml b/examples/dubbo/go-server/profiles/release/server.yml
index 5431df1172..9c9ad5c15c 100644
--- a/examples/dubbo/go-server/profiles/release/server.yml
+++ b/examples/dubbo/go-server/profiles/release/server.yml
@@ -1,5 +1,6 @@
# dubbo server yaml configure file
+
# application config
application_config:
organization : "ikurento.com"
@@ -7,18 +8,17 @@ application_config:
module : "dubbogo user-info server"
version : "0.0.1"
owner : "ZX"
- environment : "dev"
+ environment : "release"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
@@ -26,9 +26,7 @@ registries :
services:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
+ "UserProvider":
protocol : "dubbo"
# 相当于dubbo.xml中的interface
interface : "com.ikurento.user.UserProvider"
@@ -36,17 +34,16 @@ services:
warmup: "100"
cluster: "failover"
methods:
- - name: "GetUser"
- retries: 1
- loadbalance: "random"
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
protocols:
- - name: "dubbo"
+ "dubbo1":
+ name: "dubbo"
# ip : "127.0.0.1"
- port : 20000
- #- name: "jsonrpc"
- # ip: "127.0.0.1"
- # port: 20001
+ port: 20000
+
protocol_conf:
dubbo:
diff --git a/examples/dubbo/go-server/profiles/test/server.yml b/examples/dubbo/go-server/profiles/test/server.yml
index 5431df1172..69d68279d8 100644
--- a/examples/dubbo/go-server/profiles/test/server.yml
+++ b/examples/dubbo/go-server/profiles/test/server.yml
@@ -1,5 +1,6 @@
# dubbo server yaml configure file
+
# application config
application_config:
organization : "ikurento.com"
@@ -7,18 +8,17 @@ application_config:
module : "dubbogo user-info server"
version : "0.0.1"
owner : "ZX"
- environment : "dev"
+ environment : "test"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
@@ -26,9 +26,7 @@ registries :
services:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
+ "UserProvider":
protocol : "dubbo"
# 相当于dubbo.xml中的interface
interface : "com.ikurento.user.UserProvider"
@@ -36,17 +34,16 @@ services:
warmup: "100"
cluster: "failover"
methods:
- - name: "GetUser"
- retries: 1
- loadbalance: "random"
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
protocols:
- - name: "dubbo"
+ "dubbo1":
+ name: "dubbo"
# ip : "127.0.0.1"
- port : 20000
- #- name: "jsonrpc"
- # ip: "127.0.0.1"
- # port: 20001
+ port: 20000
+
protocol_conf:
dubbo:
diff --git a/examples/dubbo/with-configcenter-go-client/app/client.go b/examples/dubbo/with-configcenter-go-client/app/client.go
new file mode 100644
index 0000000000..867e17dc85
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/app/client.go
@@ -0,0 +1,152 @@
+/*
+ * 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"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+import (
+ "github.com/dubbogo/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"
+
+ _ "github.com/apache/dubbo-go/cluster/cluster_impl"
+ _ "github.com/apache/dubbo-go/cluster/loadbalance"
+ _ "github.com/apache/dubbo-go/config_center/zookeeper"
+ _ "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() {
+
+ hessian.RegisterJavaEnum(Gender(MAN))
+ hessian.RegisterJavaEnum(Gender(WOMAN))
+ hessian.RegisterPOJO(&User{})
+
+ config.Load()
+
+ println("\n\n\necho")
+ res, err := userProvider.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 = userProvider.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 := userProvider.GetUser0("A003", "Moorse")
+ if err != nil {
+ panic(err)
+ }
+ println("response result: %v", ret)
+
+ println("\n\n\nstart to test dubbo - GetUsers")
+ ret1, err := userProvider.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 = userProvider.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 = userProvider.GetUser3()
+ if err != nil {
+ panic(err)
+ }
+ println("succ!")
+
+ 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)
+ }
+
+ println("\n\n\nstart to test dubbo illegal method")
+ err = userProvider.GetUser1(context.TODO(), []interface{}{"A003"}, user)
+ if err != nil {
+ panic(err)
+ }
+
+ 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)*time.Second, func() {
+ logger.Warnf("app exit now by force...")
+ os.Exit(1)
+ })
+
+ // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
+ fmt.Println("app exit now...")
+ return
+ }
+ }
+}
+
+func println(format string, args ...interface{}) {
+ fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...)
+}
diff --git a/examples/dubbo/with-configcenter-go-client/app/user.go b/examples/dubbo/with-configcenter-go-client/app/user.go
new file mode 100644
index 0000000000..d491c36333
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/app/user.go
@@ -0,0 +1,117 @@
+/*
+ * 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 (
+ hessian "github.com/dubbogo/hessian2"
+)
+
+import (
+ "github.com/apache/dubbo-go/config"
+)
+
+type Gender hessian.JavaEnum
+
+var userProvider = new(UserProvider)
+
+func init() {
+ config.SetConsumerService(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
+}
+
+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 (User) JavaClassName() string {
+ return "com.ikurento.user.User"
+}
+
+type UserProvider 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) Service() string {
+ return "com.ikurento.user.UserProvider"
+}
+
+func (u *UserProvider) Version() string {
+ return ""
+}
diff --git a/examples/dubbo/with-configcenter-go-client/app/version.go b/examples/dubbo/with-configcenter-go-client/app/version.go
new file mode 100644
index 0000000000..c6138584f1
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/app/version.go
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+var (
+ Version = "2.6.0"
+)
diff --git a/examples/dubbo/with-configcenter-go-client/assembly/bin/load.sh b/examples/dubbo/with-configcenter-go-client/assembly/bin/load.sh
new file mode 100644
index 0000000000..07d5d15eac
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/common/app.properties b/examples/dubbo/with-configcenter-go-client/assembly/common/app.properties
new file mode 100644
index 0000000000..6bbd6db850
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/common/build.sh b/examples/dubbo/with-configcenter-go-client/assembly/common/build.sh
new file mode 100644
index 0000000000..e72418297a
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/linux/dev.sh b/examples/dubbo/with-configcenter-go-client/assembly/linux/dev.sh
new file mode 100644
index 0000000000..3373f01b94
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/linux/release.sh b/examples/dubbo/with-configcenter-go-client/assembly/linux/release.sh
new file mode 100644
index 0000000000..34867b8b34
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/linux/test.sh b/examples/dubbo/with-configcenter-go-client/assembly/linux/test.sh
new file mode 100644
index 0000000000..1bbbefd1e1
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/mac/dev.sh b/examples/dubbo/with-configcenter-go-client/assembly/mac/dev.sh
new file mode 100644
index 0000000000..b68ac83b65
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/mac/release.sh b/examples/dubbo/with-configcenter-go-client/assembly/mac/release.sh
new file mode 100644
index 0000000000..688288b3b1
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/mac/test.sh b/examples/dubbo/with-configcenter-go-client/assembly/mac/test.sh
new file mode 100644
index 0000000000..56d6c11ecd
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/windows/dev.sh b/examples/dubbo/with-configcenter-go-client/assembly/windows/dev.sh
new file mode 100644
index 0000000000..91cf6f23bc
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/windows/release.sh b/examples/dubbo/with-configcenter-go-client/assembly/windows/release.sh
new file mode 100644
index 0000000000..f317720bd5
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-client/assembly/windows/test.sh b/examples/dubbo/with-configcenter-go-client/assembly/windows/test.sh
new file mode 100644
index 0000000000..7dd2bec526
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/with-configcenter-go-client/profiles/dev/client.yml b/examples/dubbo/with-configcenter-go-client/profiles/dev/client.yml
new file mode 100644
index 0000000000..c809041f14
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/profiles/dev/client.yml
@@ -0,0 +1,40 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "dubbo"
+ 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/dubbo/with-configcenter-go-client/profiles/dev/log.yml b/examples/dubbo/with-configcenter-go-client/profiles/dev/log.yml
new file mode 100644
index 0000000000..59fa4279ad
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/with-configcenter-go-client/profiles/release/client.yml b/examples/dubbo/with-configcenter-go-client/profiles/release/client.yml
new file mode 100644
index 0000000000..c809041f14
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/profiles/release/client.yml
@@ -0,0 +1,40 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "dubbo"
+ 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/dubbo/with-configcenter-go-client/profiles/release/log.yml b/examples/dubbo/with-configcenter-go-client/profiles/release/log.yml
new file mode 100644
index 0000000000..e0514be020
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/with-configcenter-go-client/profiles/test/client.yml b/examples/dubbo/with-configcenter-go-client/profiles/test/client.yml
new file mode 100644
index 0000000000..c809041f14
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-client/profiles/test/client.yml
@@ -0,0 +1,40 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "dubbo"
+ 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/dubbo/with-configcenter-go-client/profiles/test/log.yml b/examples/dubbo/with-configcenter-go-client/profiles/test/log.yml
new file mode 100644
index 0000000000..baee0b7248
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/app/server.go b/examples/dubbo/with-configcenter-go-server/app/server.go
new file mode 100644
index 0000000000..d832ae8a29
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/app/server.go
@@ -0,0 +1,86 @@
+/*
+ * 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 (
+ hessian "github.com/dubbogo/hessian2"
+)
+
+import (
+ _ "github.com/apache/dubbo-go/cluster/cluster_impl"
+ _ "github.com/apache/dubbo-go/cluster/loadbalance"
+ "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/config_center/zookeeper"
+ _ "github.com/apache/dubbo-go/filter/impl"
+ _ "github.com/apache/dubbo-go/protocol/dubbo"
+ _ "github.com/apache/dubbo-go/registry/protocol"
+ _ "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() {
+
+ // ------for hessian2------
+ hessian.RegisterJavaEnum(Gender(MAN))
+ hessian.RegisterJavaEnum(Gender(WOMAN))
+ hessian.RegisterPOJO(&User{})
+ // ------------
+
+ 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(float64(survivalTimeout)*float64(time.Second)), func() {
+ logger.Warnf("app exit now by force...")
+ os.Exit(1)
+ })
+
+ // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
+ fmt.Println("provider app exit now...")
+ return
+ }
+ }
+}
diff --git a/examples/dubbo/with-configcenter-go-server/app/user.go b/examples/dubbo/with-configcenter-go-server/app/user.go
new file mode 100644
index 0000000000..e4400cc270
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/app/user.go
@@ -0,0 +1,195 @@
+/*
+ * 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"
+ hessian "github.com/dubbogo/hessian2"
+)
+
+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) GetErr(ctx context.Context, req []interface{}, rsp *User) error {
+ return hessian.NewThrowable("exception")
+}
+
+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) 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 (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/with-configcenter-go-server/app/version.go b/examples/dubbo/with-configcenter-go-server/app/version.go
new file mode 100644
index 0000000000..c6138584f1
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/app/version.go
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+var (
+ Version = "2.6.0"
+)
diff --git a/examples/dubbo/with-configcenter-go-server/assembly/bin/load.sh b/examples/dubbo/with-configcenter-go-server/assembly/bin/load.sh
new file mode 100644
index 0000000000..47fc5e38de
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/common/app.properties b/examples/dubbo/with-configcenter-go-server/assembly/common/app.properties
new file mode 100644
index 0000000000..dffb755b08
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/common/build.sh b/examples/dubbo/with-configcenter-go-server/assembly/common/build.sh
new file mode 100644
index 0000000000..15ac904f7c
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/linux/dev.sh b/examples/dubbo/with-configcenter-go-server/assembly/linux/dev.sh
new file mode 100644
index 0000000000..55886f09fb
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/linux/release.sh b/examples/dubbo/with-configcenter-go-server/assembly/linux/release.sh
new file mode 100644
index 0000000000..9772ad9614
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/linux/test.sh b/examples/dubbo/with-configcenter-go-server/assembly/linux/test.sh
new file mode 100644
index 0000000000..2fc4a98862
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/mac/dev.sh b/examples/dubbo/with-configcenter-go-server/assembly/mac/dev.sh
new file mode 100644
index 0000000000..5dfa78490b
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/mac/release.sh b/examples/dubbo/with-configcenter-go-server/assembly/mac/release.sh
new file mode 100644
index 0000000000..1ec21c7b51
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/mac/test.sh b/examples/dubbo/with-configcenter-go-server/assembly/mac/test.sh
new file mode 100644
index 0000000000..d34914c7db
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/windows/dev.sh b/examples/dubbo/with-configcenter-go-server/assembly/windows/dev.sh
new file mode 100644
index 0000000000..97fbb6f698
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/windows/release.sh b/examples/dubbo/with-configcenter-go-server/assembly/windows/release.sh
new file mode 100644
index 0000000000..782cb10c78
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/assembly/windows/test.sh b/examples/dubbo/with-configcenter-go-server/assembly/windows/test.sh
new file mode 100644
index 0000000000..2037ddecf2
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/profiles/dev/log.yml b/examples/dubbo/with-configcenter-go-server/profiles/dev/log.yml
new file mode 100644
index 0000000000..59fa4279ad
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/dubbo/with-configcenter-go-server/profiles/dev/server.yml b/examples/dubbo/with-configcenter-go-server/profiles/dev/server.yml
new file mode 100644
index 0000000000..05f758592f
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/profiles/dev/server.yml
@@ -0,0 +1,41 @@
+# dubbo server yaml configure file
+
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
+
+services:
+ "UserProvider":
+ protocol : "dubbo"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+protocol_conf:
+ dubbo:
+ session_number: 700
+ fail_fast_timeout: "5s"
+ 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/dubbo/with-configcenter-go-server/profiles/release/log.yml b/examples/dubbo/with-configcenter-go-server/profiles/release/log.yml
new file mode 100644
index 0000000000..e0514be020
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/with-configcenter-go-server/profiles/release/server.yml b/examples/dubbo/with-configcenter-go-server/profiles/release/server.yml
new file mode 100644
index 0000000000..05f758592f
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/profiles/release/server.yml
@@ -0,0 +1,41 @@
+# dubbo server yaml configure file
+
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
+
+services:
+ "UserProvider":
+ protocol : "dubbo"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+protocol_conf:
+ dubbo:
+ session_number: 700
+ fail_fast_timeout: "5s"
+ 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/dubbo/with-configcenter-go-server/profiles/test/log.yml b/examples/dubbo/with-configcenter-go-server/profiles/test/log.yml
new file mode 100644
index 0000000000..baee0b7248
--- /dev/null
+++ b/examples/dubbo/with-configcenter-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/with-configcenter-go-server/profiles/test/server.yml b/examples/dubbo/with-configcenter-go-server/profiles/test/server.yml
new file mode 100644
index 0000000000..05f758592f
--- /dev/null
+++ b/examples/dubbo/with-configcenter-go-server/profiles/test/server.yml
@@ -0,0 +1,41 @@
+# dubbo server yaml configure file
+
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
+
+services:
+ "UserProvider":
+ protocol : "dubbo"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+protocol_conf:
+ dubbo:
+ session_number: 700
+ fail_fast_timeout: "5s"
+ 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/jsonrpc/go-client/app/client.go b/examples/jsonrpc/go-client/app/client.go
index 4c7b5146f9..478a88d194 100644
--- a/examples/jsonrpc/go-client/app/client.go
+++ b/examples/jsonrpc/go-client/app/client.go
@@ -49,10 +49,7 @@ var (
// export APP_LOG_CONF_FILE="xxx"
func main() {
- conLen, _ := config.Load()
- if conLen == 0 {
- panic("conMap is nil")
- }
+ config.Load()
println("\n\n\necho")
res, err := userProvider.Echo(context.TODO(), "OK")
diff --git a/examples/jsonrpc/go-client/profiles/dev/client.yml b/examples/jsonrpc/go-client/profiles/dev/client.yml
index e82a200e1c..9f0b3ce0aa 100644
--- a/examples/jsonrpc/go-client/profiles/dev/client.yml
+++ b/examples/jsonrpc/go-client/profiles/dev/client.yml
@@ -16,25 +16,21 @@ application_config:
environment : "dev"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "jsonrpc"
# version : "2.0"
# group: "as"
diff --git a/examples/jsonrpc/go-client/profiles/release/client.yml b/examples/jsonrpc/go-client/profiles/release/client.yml
index f7e7df4036..fa9c87f855 100644
--- a/examples/jsonrpc/go-client/profiles/release/client.yml
+++ b/examples/jsonrpc/go-client/profiles/release/client.yml
@@ -1,6 +1,5 @@
# dubbo client yaml configure file
-
check: true
# client
request_timeout : "3s"
@@ -9,33 +8,29 @@ 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 :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "jsonrpc"
# version : "2.0"
# group: "as"
@@ -44,3 +39,27 @@ references:
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-client/profiles/test/client.yml b/examples/jsonrpc/go-client/profiles/test/client.yml
index e4a6c4b166..392b8496f8 100644
--- a/examples/jsonrpc/go-client/profiles/test/client.yml
+++ b/examples/jsonrpc/go-client/profiles/test/client.yml
@@ -8,33 +8,29 @@ 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 : "test"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
references:
- - registries :
- - "hangzhouzk"
-# - "shanghaizk"
-
+ "UserProvider":
protocol : "jsonrpc"
# version : "2.0"
# group: "as"
@@ -43,3 +39,27 @@ references:
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/server.go b/examples/jsonrpc/go-server/app/server.go
index ba747497bf..8a226e23ad 100644
--- a/examples/jsonrpc/go-server/app/server.go
+++ b/examples/jsonrpc/go-server/app/server.go
@@ -48,10 +48,7 @@ var (
// export APP_LOG_CONF_FILE="xxx"
func main() {
- _, proLen := config.Load()
- if proLen == 0 {
- panic("proMap is nil")
- }
+ config.Load()
initSignal()
}
diff --git a/examples/jsonrpc/go-server/profiles/dev/server.yml b/examples/jsonrpc/go-server/profiles/dev/server.yml
index 70e62b20c8..94e92dcc65 100644
--- a/examples/jsonrpc/go-server/profiles/dev/server.yml
+++ b/examples/jsonrpc/go-server/profiles/dev/server.yml
@@ -10,15 +10,14 @@ application_config:
environment : "dev"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
@@ -26,9 +25,7 @@ registries :
services:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
+ "UserProvider":
protocol : "jsonrpc"
# 相当于dubbo.xml中的interface
interface : "com.ikurento.user.UserProvider"
@@ -44,7 +41,8 @@ protocols:
#- name: "dubbo"
# ip : "127.0.0.1"
# port : 20000
- - name: "jsonrpc"
+ "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
index 1ded448a13..0b4f441f8c 100644
--- a/examples/jsonrpc/go-server/profiles/release/server.yml
+++ b/examples/jsonrpc/go-server/profiles/release/server.yml
@@ -2,49 +2,48 @@
# application config
application_config:
- organization : "ikurento.com"
- name : "BDTService"
- module : "dubbogo user-info server"
- version : "0.0.1"
- owner : "ZX"
- environment : "dev"
+ organization : "ikurento.com"
+ name : "BDTService"
+ module : "dubbogo user-info server"
+ version : "0.0.1"
+ owner : "ZX"
+ environment : "release"
registries :
-- id: "hangzhouzk"
- type: "zookeeper"
- timeout : "3s"
- address: "127.0.0.1:2181"
- username: ""
- password: ""
-
-- id: "shanghaizk"
- type: "zookeeper"
- timeout : "3s"
- address: "127.0.0.1:2182"
- username: ""
- password: ""
+ "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:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
- protocol : "jsonrpc"
- # 相当于dubbo.xml中的interface
- interface : "com.ikurento.user.UserProvider"
- loadbalance: "random"
- warmup: "100"
- cluster: "failover"
- methods:
- - name: "GetUser"
- retries: 1
- loadbalance: "random"
+ "UserProvider":
+ 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
- - name: "jsonrpc"
+ "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
index 5948fd78f6..e8d7135a82 100644
--- a/examples/jsonrpc/go-server/profiles/test/server.yml
+++ b/examples/jsonrpc/go-server/profiles/test/server.yml
@@ -2,47 +2,47 @@
# application config
application_config:
- organization : "ikurento.com"
- name : "BDTService"
- module : "dubbogo user-info server"
- version : "0.0.1"
- owner : "ZX"
- environment : "dev"
+ organization : "ikurento.com"
+ name : "BDTService"
+ module : "dubbogo user-info server"
+ version : "0.0.1"
+ owner : "ZX"
+ environment : "test"
registries :
- - id: "hangzhouzk"
- type: "zookeeper"
+ "hangzhouzk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2181"
username: ""
password: ""
-
- - id: "shanghaizk"
- type: "zookeeper"
+ "shanghaizk":
+ protocol: "zookeeper"
timeout : "3s"
address: "127.0.0.1:2182"
username: ""
password: ""
+
services:
- - registries:
- - "hangzhouzk"
-# - "shanghaizk"
- protocol : "jsonrpc"
- # 相当于dubbo.xml中的interface
- interface : "com.ikurento.user.UserProvider"
- loadbalance: "random"
- warmup: "100"
- cluster: "failover"
- methods:
- - name: "GetUser"
- retries: 1
- loadbalance: "random"
+ "UserProvider":
+ 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
- - name: "jsonrpc"
+ "jsonrpc1":
+ name: "jsonrpc"
ip: "127.0.0.1"
port: 20001
+
diff --git a/examples/jsonrpc/with-configcenter-go-client/app/client.go b/examples/jsonrpc/with-configcenter-go-client/app/client.go
new file mode 100644
index 0000000000..642b45a934
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/app/client.go
@@ -0,0 +1,137 @@
+/*
+ * 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"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+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/jsonrpc"
+ _ "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/config_center/zookeeper"
+ _ "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() {
+
+ config.Load()
+
+ println("\n\n\necho")
+ res, err := userProvider.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 = userProvider.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 := userProvider.GetUser0("A003", "Moorse")
+ if err != nil {
+ panic(err)
+ }
+ println("response result: %v", ret)
+
+ println("\n\n\nstart to test jsonrpc - GetUsers")
+ ret1, err := userProvider.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 = userProvider.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 = userProvider.GetUser3()
+ if err != nil {
+ panic(err)
+ }
+ println("succ!")
+
+ println("\n\n\nstart to test jsonrpc illegal method")
+ err = userProvider.GetUser1(context.TODO(), []interface{}{"A003"}, user)
+ if err != nil {
+ panic(err)
+ }
+
+ 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)*time.Second, func() {
+ logger.Warnf("app exit now by force...")
+ os.Exit(1)
+ })
+
+ // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
+ fmt.Println("app exit now...")
+ return
+ }
+ }
+}
+
+func println(format string, args ...interface{}) {
+ fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...)
+}
diff --git a/examples/jsonrpc/with-configcenter-go-client/app/user.go b/examples/jsonrpc/with-configcenter-go-client/app/user.go
new file mode 100644
index 0000000000..ca98b1af0b
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/app/user.go
@@ -0,0 +1,67 @@
+/*
+ * 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/config"
+)
+
+var userProvider = new(UserProvider)
+
+func init() {
+ config.SetConsumerService(userProvider)
+}
+
+type JsonRPCUser struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Age int64 `json:"age"`
+ Time int64 `json:"time"`
+ Sex string `json:"sex"`
+}
+
+func (u JsonRPCUser) String() string {
+ return fmt.Sprintf(
+ "User{ID:%s, Name:%s, Age:%d, Time:%s, Sex:%s}",
+ u.ID, u.Name, u.Age, time.Unix(u.Time, 0).Format("2006-01-02 15:04:05.99999"), u.Sex,
+ )
+}
+
+type UserProvider 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) Service() string {
+ return "com.ikurento.user.UserProvider"
+}
+
+func (u *UserProvider) Version() string {
+ return ""
+}
diff --git a/examples/jsonrpc/with-configcenter-go-client/app/version.go b/examples/jsonrpc/with-configcenter-go-client/app/version.go
new file mode 100644
index 0000000000..c6138584f1
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/app/version.go
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+var (
+ Version = "2.6.0"
+)
diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh
new file mode 100644
index 0000000000..07d5d15eac
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/common/app.properties b/examples/jsonrpc/with-configcenter-go-client/assembly/common/app.properties
new file mode 100644
index 0000000000..6bbd6db850
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/common/build.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/common/build.sh
new file mode 100644
index 0000000000..06b212db6c
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh
new file mode 100644
index 0000000000..3373f01b94
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh
new file mode 100644
index 0000000000..34867b8b34
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh
new file mode 100644
index 0000000000..1bbbefd1e1
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh
new file mode 100644
index 0000000000..b68ac83b65
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh
new file mode 100644
index 0000000000..688288b3b1
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh
new file mode 100644
index 0000000000..56d6c11ecd
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh
new file mode 100644
index 0000000000..91cf6f23bc
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh
new file mode 100644
index 0000000000..f317720bd5
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh b/examples/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh
new file mode 100644
index 0000000000..7dd2bec526
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml b/examples/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml
new file mode 100644
index 0000000000..3770f52b83
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml
@@ -0,0 +1,16 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "jsonrpc"
+ 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/jsonrpc/with-configcenter-go-client/profiles/dev/log.yml
new file mode 100644
index 0000000000..59fa4279ad
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/profiles/release/client.yml b/examples/jsonrpc/with-configcenter-go-client/profiles/release/client.yml
new file mode 100644
index 0000000000..3770f52b83
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/profiles/release/client.yml
@@ -0,0 +1,16 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "jsonrpc"
+ 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/jsonrpc/with-configcenter-go-client/profiles/release/log.yml
new file mode 100644
index 0000000000..e0514be020
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-client/profiles/test/client.yml b/examples/jsonrpc/with-configcenter-go-client/profiles/test/client.yml
new file mode 100644
index 0000000000..3770f52b83
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-client/profiles/test/client.yml
@@ -0,0 +1,16 @@
+# dubbo client yaml configure file
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.client.properties"
+
+references:
+ "UserProvider":
+ protocol : "jsonrpc"
+ 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/jsonrpc/with-configcenter-go-client/profiles/test/log.yml
new file mode 100644
index 0000000000..baee0b7248
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/app/server.go b/examples/jsonrpc/with-configcenter-go-server/app/server.go
new file mode 100644
index 0000000000..851a97c155
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/app/server.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 main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+import (
+ _ "github.com/apache/dubbo-go/cluster/cluster_impl"
+ _ "github.com/apache/dubbo-go/cluster/loadbalance"
+ "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/config_center/zookeeper"
+ _ "github.com/apache/dubbo-go/filter/impl"
+ _ "github.com/apache/dubbo-go/protocol/jsonrpc"
+ _ "github.com/apache/dubbo-go/registry/protocol"
+ _ "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(float64(survivalTimeout)*float64(time.Second)), func() {
+ logger.Warnf("app exit now by force...")
+ os.Exit(1)
+ })
+
+ // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
+ fmt.Println("provider app exit now...")
+ return
+ }
+ }
+}
diff --git a/examples/jsonrpc/with-configcenter-go-server/app/user.go b/examples/jsonrpc/with-configcenter-go-server/app/user.go
new file mode 100644
index 0000000000..fbe6f3339c
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/app/user.go
@@ -0,0 +1,159 @@
+/*
+ * 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 (
+ 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) 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 (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/with-configcenter-go-server/app/version.go b/examples/jsonrpc/with-configcenter-go-server/app/version.go
new file mode 100644
index 0000000000..c6138584f1
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/app/version.go
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+var (
+ Version = "2.6.0"
+)
diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh
new file mode 100644
index 0000000000..47fc5e38de
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/common/app.properties b/examples/jsonrpc/with-configcenter-go-server/assembly/common/app.properties
new file mode 100644
index 0000000000..dffb755b08
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/common/build.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/common/build.sh
new file mode 100644
index 0000000000..15ac904f7c
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh
new file mode 100644
index 0000000000..55886f09fb
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh
new file mode 100644
index 0000000000..9772ad9614
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh
new file mode 100644
index 0000000000..2fc4a98862
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh
new file mode 100644
index 0000000000..5dfa78490b
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh
new file mode 100644
index 0000000000..1ec21c7b51
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh
new file mode 100644
index 0000000000..d34914c7db
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh
new file mode 100644
index 0000000000..97fbb6f698
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh
new file mode 100644
index 0000000000..782cb10c78
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh b/examples/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh
new file mode 100644
index 0000000000..2037ddecf2
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml
new file mode 100644
index 0000000000..59fa4279ad
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml
new file mode 100644
index 0000000000..5c2a2fe2cb
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml
@@ -0,0 +1,22 @@
+# dubbo server yaml configure file
+
+# application config
+
+services:
+ "UserProvider":
+ protocol : "jsonrpc"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/release/log.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/release/log.yml
new file mode 100644
index 0000000000..e0514be020
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/profiles/release/server.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/release/server.yml
new file mode 100644
index 0000000000..82c9fa66ad
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/profiles/release/server.yml
@@ -0,0 +1,25 @@
+# dubbo server yaml configure file
+
+# application config
+
+services:
+ "UserProvider":
+ protocol : "jsonrpc"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
+
+
+
diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/test/log.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/test/log.yml
new file mode 100644
index 0000000000..baee0b7248
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-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/jsonrpc/with-configcenter-go-server/profiles/test/server.yml b/examples/jsonrpc/with-configcenter-go-server/profiles/test/server.yml
new file mode 100644
index 0000000000..82c9fa66ad
--- /dev/null
+++ b/examples/jsonrpc/with-configcenter-go-server/profiles/test/server.yml
@@ -0,0 +1,25 @@
+# dubbo server yaml configure file
+
+# application config
+
+services:
+ "UserProvider":
+ protocol : "jsonrpc"
+ # 相当于dubbo.xml中的interface
+ interface : "com.ikurento.user.UserProvider"
+ loadbalance: "random"
+ warmup: "100"
+ cluster: "failover"
+ methods:
+ - name: "GetUser"
+ retries: 1
+ loadbalance: "random"
+
+config_center:
+ protocol: "zookeeper"
+ address: "127.0.0.1:2181"
+ group: "dubbo"
+ config_file: "dubbo.properties"
+
+
+
diff --git a/go.mod b/go.mod
index 213d7ee8e8..309be9e00f 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/apache/dubbo-go
require (
github.com/dubbogo/getty v1.0.7
github.com/dubbogo/hessian2 v1.0.2
+ github.com/magiconair/properties v1.8.1
github.com/pkg/errors v0.8.1
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec
github.com/stretchr/testify v1.3.0
diff --git a/go.sum b/go.sum
index f39e814c86..4a612ca776 100644
--- a/go.sum
+++ b/go.sum
@@ -9,6 +9,8 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
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/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
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=
@@ -27,7 +29,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
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/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/registry/directory/directory.go b/registry/directory/directory.go
index a4a9263156..11687f82ee 100644
--- a/registry/directory/directory.go
+++ b/registry/directory/directory.go
@@ -131,11 +131,11 @@ func (dir *registryDirectory) update(res *registry.ServiceEvent) {
func (dir *registryDirectory) refreshInvokers(res *registry.ServiceEvent) {
switch res.Action {
- case remoting.Add:
- //dir.cacheService.Add(res.Path, dir.serviceTTL)
+ case remoting.EventTypeAdd:
+ //dir.cacheService.EventTypeAdd(res.Path, dir.serviceTTL)
dir.cacheInvoker(res.Service)
- case remoting.Del:
- //dir.cacheService.Del(res.Path, dir.serviceTTL)
+ case remoting.EventTypeDel:
+ //dir.cacheService.EventTypeDel(res.Path, dir.serviceTTL)
dir.uncacheInvoker(res.Service)
logger.Infof("selector delete service url{%s}", res.Service)
default:
diff --git a/registry/directory/directory_test.go b/registry/directory/directory_test.go
index a40452756c..f31165d0a2 100644
--- a/registry/directory/directory_test.go
+++ b/registry/directory/directory_test.go
@@ -51,7 +51,7 @@ func TestSubscribe_Delete(t *testing.T) {
registryDirectory, mockRegistry := normalRegistryDir()
time.Sleep(1e9)
assert.Len(t, registryDirectory.cacheInvokers, 3)
- mockRegistry.MockEvent(®istry.ServiceEvent{Action: remoting.Del, Service: *common.NewURLWithOptions(common.WithPath("TEST0"), common.WithProtocol("dubbo"))})
+ mockRegistry.MockEvent(®istry.ServiceEvent{Action: remoting.EventTypeDel, Service: *common.NewURLWithOptions(common.WithPath("TEST0"), common.WithProtocol("dubbo"))})
time.Sleep(1e9)
assert.Len(t, registryDirectory.cacheInvokers, 2)
}
@@ -81,7 +81,7 @@ func TestSubscribe_Group(t *testing.T) {
urlmap.Set(constant.GROUP_KEY, "group1")
urlmap.Set(constant.CLUSTER_KEY, "failover") //to test merge url
for i := 0; i < 3; i++ {
- mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.Add, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"),
+ mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.EventTypeAdd, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"),
common.WithParams(urlmap))})
}
//for group2
@@ -89,7 +89,7 @@ func TestSubscribe_Group(t *testing.T) {
urlmap2.Set(constant.GROUP_KEY, "group2")
urlmap2.Set(constant.CLUSTER_KEY, "failover") //to test merge url
for i := 0; i < 3; i++ {
- mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.Add, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"),
+ mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.EventTypeAdd, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"),
common.WithParams(urlmap2))})
}
@@ -129,7 +129,7 @@ func normalRegistryDir() (*registryDirectory, *registry.MockRegistry) {
go registryDirectory.Subscribe(*common.NewURLWithOptions(common.WithPath("testservice")))
for i := 0; i < 3; i++ {
- mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.Add, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"))})
+ mockRegistry.(*registry.MockRegistry).MockEvent(®istry.ServiceEvent{Action: remoting.EventTypeAdd, Service: *common.NewURLWithOptions(common.WithPath("TEST"+strconv.FormatInt(int64(i), 10)), common.WithProtocol("dubbo"))})
}
return registryDirectory, mockRegistry.(*registry.MockRegistry)
}
diff --git a/registry/zookeeper/listener.go b/registry/zookeeper/listener.go
index 4f3cf1e19a..67f2037060 100644
--- a/registry/zookeeper/listener.go
+++ b/registry/zookeeper/listener.go
@@ -19,6 +19,7 @@ package zookeeper
import (
"context"
+ "strings"
)
import (
perrors "github.com/pkg/errors"
@@ -33,10 +34,10 @@ import (
type RegistryDataListener struct {
interestedURL []*common.URL
- listener *RegistryConfigurationListener
+ listener remoting.ConfigurationListener
}
-func NewRegistryDataListener(listener *RegistryConfigurationListener) *RegistryDataListener {
+func NewRegistryDataListener(listener remoting.ConfigurationListener) *RegistryDataListener {
return &RegistryDataListener{listener: listener, interestedURL: []*common.URL{}}
}
func (l *RegistryDataListener) AddInterestedURL(url *common.URL) {
@@ -44,9 +45,11 @@ func (l *RegistryDataListener) AddInterestedURL(url *common.URL) {
}
func (l *RegistryDataListener) DataChange(eventType remoting.Event) bool {
- serviceURL, err := common.NewURL(context.TODO(), eventType.Content)
+ //截取最后一位
+ url := eventType.Path[strings.Index(eventType.Path, "/providers/")+len("/providers/"):]
+ serviceURL, err := common.NewURL(context.TODO(), url)
if err != nil {
- logger.Errorf("Listen NewURL(r{%s}) = error{%v}", eventType.Content, err)
+ logger.Errorf("Listen NewURL(r{%s}) = error{%v}", url, err)
return false
}
for _, v := range l.interestedURL {
@@ -86,7 +89,7 @@ func (l *RegistryConfigurationListener) Next() (*registry.ServiceEvent, error) {
case e := <-l.events:
logger.Debugf("got zk event %s", e)
- if e.ConfigType == remoting.Del && !l.valid() {
+ if e.ConfigType == remoting.EventTypeDel && !l.valid() {
logger.Warnf("update @result{%s}. But its connection to registry is invalid", e.Value)
continue
}
diff --git a/registry/zookeeper/listener_test.go b/registry/zookeeper/listener_test.go
new file mode 100644
index 0000000000..7ebc32b8a5
--- /dev/null
+++ b/registry/zookeeper/listener_test.go
@@ -0,0 +1,23 @@
+package zookeeper
+
+import (
+ "context"
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/remoting"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func Test_DataChange(t *testing.T) {
+ listener := NewRegistryDataListener(&MockDataListener{})
+ url, _ := common.NewURL(context.TODO(), "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)
+ int := 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"})
+ assert.Equal(t, true, int)
+}
+
+type MockDataListener struct {
+}
+
+func (*MockDataListener) Process(configType *remoting.ConfigChangeEvent) {
+}
diff --git a/remoting/listener.go b/remoting/listener.go
index 37f75d4652..da30f6989d 100644
--- a/remoting/listener.go
+++ b/remoting/listener.go
@@ -44,8 +44,9 @@ func (c ConfigChangeEvent) String() string {
type EventType int
const (
- Add = iota
- Del
+ EventTypeAdd = iota
+ EventTypeDel
+ EvnetTypeUpdate
)
var serviceEventTypeStrings = [...]string{
diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go
index 93382ed265..d1d5f9900d 100644
--- a/remoting/zookeeper/client.go
+++ b/remoting/zookeeper/client.go
@@ -100,7 +100,7 @@ func WithZkName(name string) Option {
}
}
-func ValidateZookeeperClient(container ZkClientContainer, opts ...Option) error {
+func ValidateZookeeperClient(container zkClientFacade, opts ...Option) error {
var (
err error
)
@@ -543,7 +543,7 @@ func (z *ZookeeperClient) ExistW(zkPath string) (<-chan zk.Event, error) {
}
z.Unlock()
if err != nil {
- logger.Errorf("zkClient{%s}.ExistsW(path{%s}) = error{%v}.", z.name, zkPath, perrors.WithStack(err))
+ logger.Warnf("zkClient{%s}.ExistsW(path{%s}) = error{%v}.", z.name, zkPath, perrors.WithStack(err))
return nil, perrors.WithMessagef(err, "zk.ExistsW(path:%s)", zkPath)
}
if !exist {
@@ -553,3 +553,7 @@ func (z *ZookeeperClient) ExistW(zkPath string) (<-chan zk.Event, error) {
return event, nil
}
+
+func (z *ZookeeperClient) GetContent(zkPath string) ([]byte, *zk.Stat, error) {
+ return z.Conn.Get(zkPath)
+}
diff --git a/remoting/zookeeper/client_test.go b/remoting/zookeeper/client_test.go
index 4a71ebd610..f1bd0c2cb3 100644
--- a/remoting/zookeeper/client_test.go
+++ b/remoting/zookeeper/client_test.go
@@ -48,23 +48,6 @@ func verifyEventStateOrder(t *testing.T, c <-chan zk.Event, expectedStates []zk.
}
}
-func verifyEventOrder(t *testing.T, c <-chan zk.Event, expectedEvent []zk.EventType, source string) {
- for _, e := range expectedEvent {
- for {
- event, ok := <-c
- if !ok {
- t.Fatalf("unexpected channel close for %s", source)
- }
-
- if event.Type != e {
- t.Fatalf("mismatched state order from %s, expected %v, received %v", source, event, event.Type)
- }
-
- break
- }
- }
-}
-
//func Test_newZookeeperClient(t *testing.T) {
// ts, err := zk.StartTestCluster(1, nil, nil)
// if err != nil {
diff --git a/remoting/zookeeper/container.go b/remoting/zookeeper/facade.go
similarity index 96%
rename from remoting/zookeeper/container.go
rename to remoting/zookeeper/facade.go
index f869b32444..4fd800f877 100644
--- a/remoting/zookeeper/container.go
+++ b/remoting/zookeeper/facade.go
@@ -30,7 +30,7 @@ import (
"github.com/apache/dubbo-go/common/logger"
)
-type ZkClientContainer interface {
+type zkClientFacade interface {
ZkClient() *ZookeeperClient
SetZkClient(*ZookeeperClient)
ZkClientLock() *sync.Mutex
@@ -40,7 +40,7 @@ type ZkClientContainer interface {
common.Node
}
-func HandleClientRestart(r ZkClientContainer) {
+func HandleClientRestart(r zkClientFacade) {
var (
err error
diff --git a/remoting/zookeeper/facade_test.go b/remoting/zookeeper/facade_test.go
new file mode 100644
index 0000000000..46edd49bf7
--- /dev/null
+++ b/remoting/zookeeper/facade_test.go
@@ -0,0 +1,90 @@
+/*
+ * 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 zookeeper
+
+import (
+ "context"
+ "sync"
+ "testing"
+ "time"
+)
+import (
+ "github.com/samuel/go-zookeeper/zk"
+ "github.com/stretchr/testify/assert"
+)
+import (
+ "github.com/apache/dubbo-go/common"
+)
+
+type mockFacade struct {
+ client *ZookeeperClient
+ cltLock sync.Mutex
+ wg sync.WaitGroup
+ URL *common.URL
+ done chan struct{}
+}
+
+func (r *mockFacade) ZkClient() *ZookeeperClient {
+ return r.client
+}
+
+func (r *mockFacade) SetZkClient(client *ZookeeperClient) {
+ r.client = client
+}
+
+func (r *mockFacade) ZkClientLock() *sync.Mutex {
+ return &r.cltLock
+}
+
+func (r *mockFacade) WaitGroup() *sync.WaitGroup {
+ return &r.wg
+}
+
+func (r *mockFacade) GetDone() chan struct{} {
+ return r.done
+}
+
+func (r *mockFacade) GetUrl() common.URL {
+ return *r.URL
+}
+
+func (r *mockFacade) Destroy() {
+ close(r.done)
+ r.wg.Wait()
+}
+
+func (r *mockFacade) RestartCallBack() bool {
+ return true
+}
+func (r *mockFacade) IsAvailable() bool {
+ return true
+}
+
+func Test_Fascade(t *testing.T) {
+ ts, z, event, err := NewMockZookeeperClient("test", 15*time.Second)
+ assert.NoError(t, err)
+ defer ts.Stop()
+ url, _ := common.NewURL(context.Background(), "mock://127.0.0.1")
+ mock := &mockFacade{client: z, URL: &url}
+ go HandleClientRestart(mock)
+ states := []zk.State{zk.StateConnecting, zk.StateConnected, zk.StateHasSession}
+ verifyEventStateOrder(t, event, states, "event channel")
+ z.Close()
+ verifyEventStateOrder(t, event, []zk.State{zk.StateDisconnected}, "event channel")
+ //time.Sleep(2e9)
+}
diff --git a/remoting/zookeeper/listener.go b/remoting/zookeeper/listener.go
index 703d06f84e..af668a1aaf 100644
--- a/remoting/zookeeper/listener.go
+++ b/remoting/zookeeper/listener.go
@@ -29,7 +29,6 @@ import (
)
import (
- "github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/remoting"
)
@@ -50,14 +49,14 @@ func NewZkEventListener(client *ZookeeperClient) *ZkEventListener {
func (l *ZkEventListener) SetClient(client *ZookeeperClient) {
l.client = client
}
-func (l *ZkEventListener) listenServiceNodeEvent(zkPath string) bool {
+func (l *ZkEventListener) ListenServiceNodeEvent(zkPath string, listener ...remoting.DataListener) bool {
l.wg.Add(1)
defer l.wg.Done()
var zkEvent zk.Event
for {
keyEventCh, err := l.client.ExistW(zkPath)
if err != nil {
- logger.Errorf("existW{key:%s} = error{%v}", zkPath, err)
+ logger.Warnf("existW{key:%s} = error{%v}", zkPath, err)
return false
}
@@ -68,8 +67,17 @@ func (l *ZkEventListener) listenServiceNodeEvent(zkPath string) bool {
switch zkEvent.Type {
case zk.EventNodeDataChanged:
logger.Warnf("zk.ExistW(key{%s}) = event{EventNodeDataChanged}", zkPath)
+ if len(listener) > 0 {
+ content, _, _ := l.client.Conn.Get(zkEvent.Path)
+ listener[0].DataChange(remoting.Event{Path: zkEvent.Path, Action: remoting.EvnetTypeUpdate, Content: string(content)})
+ }
+
case zk.EventNodeCreated:
logger.Warnf("zk.ExistW(key{%s}) = event{EventNodeCreated}", zkPath)
+ if len(listener) > 0 {
+ content, _, _ := l.client.Conn.Get(zkEvent.Path)
+ listener[0].DataChange(remoting.Event{Path: zkEvent.Path, Action: remoting.EventTypeAdd, Content: string(content)})
+ }
case zk.EventNotWatching:
logger.Warnf("zk.ExistW(key{%s}) = event{EventNotWatching}", zkPath)
case zk.EventNodeDeleted:
@@ -112,15 +120,20 @@ func (l *ZkEventListener) handleZkNodeEvent(zkPath string, children []string, li
newNode = path.Join(zkPath, n)
logger.Infof("add zkNode{%s}", newNode)
- if !listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Add, Content: n}) {
+ content, _, err := l.client.Conn.Get(newNode)
+ if err != nil {
+ logger.Errorf("Get new node path {%v} 's content error,message is {%v}", newNode, perrors.WithStack(err))
+ }
+
+ if !listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.EventTypeAdd, Content: string(content)}) {
continue
}
// listen l service node
go func(node string) {
logger.Infof("delete zkNode{%s}", node)
- if l.listenServiceNodeEvent(node) {
+ if l.ListenServiceNodeEvent(node, listener) {
logger.Infof("delete content{%s}", n)
- listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Del, Content: n})
+ listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.EventTypeDel})
}
logger.Warnf("listenSelf(zk path{%s}) goroutine exit now", zkPath)
}(newNode)
@@ -135,15 +148,12 @@ func (l *ZkEventListener) handleZkNodeEvent(zkPath string, children []string, li
oldNode = path.Join(zkPath, n)
logger.Warnf("delete zkPath{%s}", oldNode)
- if !listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Add, Content: n}) {
- continue
- }
- logger.Warnf("delete content{%s}", n)
+
if err != nil {
logger.Errorf("NewURL(i{%s}) = error{%v}", n, perrors.WithStack(err))
continue
}
- listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Del, Content: n})
+ listener.DataChange(remoting.Event{Path: oldNode, Action: remoting.EventTypeDel})
}
}
@@ -166,7 +176,7 @@ func (l *ZkEventListener) listenDirEvent(zkPath string, listener remoting.DataLi
if MaxFailTimes <= failTimes {
failTimes = MaxFailTimes
}
- logger.Errorf("listenDirEvent(path{%s}) = error{%v}", zkPath, err)
+ logger.Warnf("listenDirEvent(path{%s}) = error{%v}", zkPath, err)
// clear the event channel
CLEAR:
for {
@@ -193,7 +203,32 @@ func (l *ZkEventListener) listenDirEvent(zkPath string, listener remoting.DataLi
}
}
failTimes = 0
+ for _, c := range children {
+
+ // listen l service node
+ dubboPath := path.Join(zkPath, c)
+ 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))
+ }
+ logger.Infof("Get children!{%s}", dubboPath)
+ if !listener.DataChange(remoting.Event{Path: dubboPath, Action: remoting.EventTypeAdd, Content: string(content)}) {
+ continue
+ }
+ logger.Infof("listen dubbo service key{%s}", dubboPath)
+ go func(zkPath string) {
+ if l.ListenServiceNodeEvent(dubboPath) {
+ listener.DataChange(remoting.Event{Path: dubboPath, Action: remoting.EventTypeDel})
+ }
+ logger.Warnf("listenSelf(zk path{%s}) goroutine exit now", zkPath)
+ }(dubboPath)
+ //liten sub path recursive
+ go func(zkPath string, listener remoting.DataListener) {
+ l.listenDirEvent(zkPath, listener)
+ logger.Warnf("listenDirEvent(zkPath{%s}) goroutine exit now", zkPath)
+ }(dubboPath, listener)
+ }
select {
case zkEvent = <-childEventCh:
logger.Warnf("get a zookeeper zkEvent{type:%s, server:%s, path:%s, state:%d-%s, err:%s}",
@@ -209,20 +244,80 @@ func (l *ZkEventListener) listenDirEvent(zkPath string, listener remoting.DataLi
}
}
+//
+//func (l *ZkEventListener) listenFileEvent(zkPath string, listener remoting.DataListener) {
+// l.wg.EventTypeAdd(1)
+// defer l.wg.Done()
+//
+// var (
+// failTimes int
+// event chan struct{}
+// zkEvent zk.Event
+// )
+// event = make(chan struct{}, 4)
+// defer close(event)
+// for {
+// // get current children for a zkPath
+// content,_, eventCh, err := l.client.Conn.GetW(zkPath)
+// if err != nil {
+// failTimes++
+// if MaxFailTimes <= failTimes {
+// failTimes = MaxFailTimes
+// }
+// logger.Errorf("listenFileEvent(path{%s}) = error{%v}", zkPath, err)
+// // clear the event channel
+// CLEAR:
+// for {
+// select {
+// case <-event:
+// default:
+// break CLEAR
+// }
+// }
+// l.client.RegisterEvent(zkPath, &event)
+// select {
+// case <-time.After(timeSecondDuration(failTimes * ConnDelay)):
+// l.client.UnregisterEvent(zkPath, &event)
+// continue
+// case <-l.client.Done():
+// l.client.UnregisterEvent(zkPath, &event)
+// logger.Warnf("client.done(), listen(path{%s}) goroutine exit now...", zkPath)
+// return
+// case <-event:
+// logger.Infof("get zk.EventNodeDataChange notify event")
+// l.client.UnregisterEvent(zkPath, &event)
+// l.handleZkNodeEvent(zkPath, nil, listener)
+// continue
+// }
+// }
+// failTimes = 0
+//
+// select {
+// case zkEvent = <-eventCh:
+// logger.Warnf("get a zookeeper zkEvent{type:%s, server:%s, path:%s, state:%d-%s, err:%s}",
+// zkEvent.Type.String(), zkEvent.Server, zkEvent.Path, zkEvent.State, StateToString(zkEvent.State), zkEvent.Err)
+//
+// l.handleZkNodeEvent(zkEvent.Path, children, listener)
+// case <-l.client.Done():
+// logger.Warnf("client.done(), listen(path{%s}) goroutine exit now...", zkPath)
+// return
+// }
+// }
+//}
+
func timeSecondDuration(sec int) time.Duration {
return time.Duration(sec) * time.Second
}
// this func is invoked by ZkConsumerRegistry::Registe/ZkConsumerRegistry::get/ZkConsumerRegistry::getListener
-// registry.go:Listen -> listenServiceEvent -> listenDirEvent -> listenServiceNodeEvent
+// registry.go:Listen -> listenServiceEvent -> listenDirEvent -> ListenServiceNodeEvent
// |
-// --------> listenServiceNodeEvent
+// --------> ListenServiceNodeEvent
func (l *ZkEventListener) ListenServiceEvent(zkPath string, listener remoting.DataListener) {
var (
- err error
- dubboPath string
- children []string
- serviceURL common.URL
+ err error
+ dubboPath string
+ children []string
)
l.pathMapLock.Lock()
@@ -241,24 +336,27 @@ func (l *ZkEventListener) ListenServiceEvent(zkPath string, listener remoting.Da
children, err = l.client.GetChildren(zkPath)
if err != nil {
children = nil
- logger.Errorf("fail to get children of zk path{%s}", zkPath)
+ logger.Warnf("fail to get children of zk path{%s}", zkPath)
}
for _, c := range children {
- if !listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Add, Content: c}) {
- continue
- }
// listen l service node
dubboPath = path.Join(zkPath, c)
+ 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))
+ }
+ if !listener.DataChange(remoting.Event{Path: dubboPath, Action: remoting.EventTypeAdd, Content: string(content)}) {
+ continue
+ }
logger.Infof("listen dubbo service key{%s}", dubboPath)
- go func(zkPath string, serviceURL common.URL) {
- if l.listenServiceNodeEvent(dubboPath) {
- logger.Debugf("delete serviceUrl{%s}", serviceURL)
- listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.Del, Content: c})
+ go func(zkPath string) {
+ if l.ListenServiceNodeEvent(dubboPath) {
+ listener.DataChange(remoting.Event{Path: dubboPath, Action: remoting.EventTypeDel})
}
logger.Warnf("listenSelf(zk path{%s}) goroutine exit now", zkPath)
- }(dubboPath, serviceURL)
+ }(dubboPath)
}
logger.Infof("listen dubbo path{%s}", zkPath)
diff --git a/remoting/zookeeper/listener_test.go b/remoting/zookeeper/listener_test.go
new file mode 100644
index 0000000000..b1f0d43d34
--- /dev/null
+++ b/remoting/zookeeper/listener_test.go
@@ -0,0 +1,117 @@
+/*
+ * 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 zookeeper
+
+import (
+ "fmt"
+ "testing"
+ "time"
+)
+import (
+ "github.com/samuel/go-zookeeper/zk"
+ "github.com/stretchr/testify/assert"
+)
+import (
+ "github.com/apache/dubbo-go/remoting"
+)
+
+func initZkData(t *testing.T) (*zk.TestCluster, *ZookeeperClient, <-chan zk.Event) {
+ ts, client, event, err := NewMockZookeeperClient("test", 15*time.Second)
+ assert.NoError(t, err)
+
+ data := `
+ dubbo.consumer.request_timeout=5s
+ 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
+`
+
+ err = client.Create("/dubbo/dubbo.properties")
+ assert.NoError(t, err)
+
+ _, err = client.Conn.Set("/dubbo/dubbo.properties", []byte(data), 0)
+ assert.NoError(t, err)
+
+ return ts, client, event
+}
+func TestListener(t *testing.T) {
+ 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
+`
+
+ ts, client, event := initZkData(t)
+ defer ts.Stop()
+ client.Wait.Add(1)
+ go client.HandleZkEvent(event)
+ listener := NewZkEventListener(client)
+ dataListener := &mockDataListener{client: client, changedData: changedData}
+ listener.ListenServiceEvent("/dubbo", dataListener)
+
+ _, err := client.Conn.Set("/dubbo/dubbo.properties", []byte(changedData), 1)
+ assert.NoError(t, err)
+ client.Wait.Wait()
+ assert.Equal(t, changedData, dataListener.eventList[1].Content)
+}
+
+type mockDataListener struct {
+ eventList []remoting.Event
+ client *ZookeeperClient
+ changedData string
+}
+
+func (m *mockDataListener) DataChange(eventType remoting.Event) bool {
+ fmt.Println(eventType)
+ m.eventList = append(m.eventList, eventType)
+ if eventType.Content == m.changedData {
+ m.client.Wait.Done()
+ }
+ return true
+}