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 +}