blob: 9f76e4cb40c73c3fa6623073bde75e19fe702f15 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package config
import (
"fmt"
"time"
)
import (
"github.com/creasty/defaults"
)
import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/logger"
"dubbo.apache.org/dubbo-go/v3/config/generic"
)
const (
MaxWheelTimeSpan = 900e9 // 900s, 15 minute
)
// ConsumerConfig is Consumer default configuration
type ConsumerConfig struct {
Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
// ConnectTimeout will be remove in 3.0 config-enhance
ConnectTimeout string `default:"3s" yaml:"connect-timeout" json:"connect-timeout,omitempty" property:"connect-timeout"`
// support string
Registry []string `yaml:"registry" json:"registry,omitempty" property:"registry"`
RequestTimeout string `default:"3s" yaml:"request-timeout" json:"request-timeout,omitempty" property:"request-timeout"`
ProxyFactory string `default:"default" yaml:"proxy" json:"proxy,omitempty" property:"proxy"`
Check bool `yaml:"check" json:"check,omitempty" property:"check"`
References map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
FilterConf interface{} `yaml:"filter-conf" json:"filter-conf,omitempty" property:"filter-conf"`
rootConfig *RootConfig
}
// Prefix dubbo.consumer
func (ConsumerConfig) Prefix() string {
return constant.ConsumerConfigPrefix
}
func (cc *ConsumerConfig) Init(rc *RootConfig) error {
if cc == nil {
return nil
}
cc.Registry = translateRegistryIds(cc.Registry)
if len(cc.Registry) <= 0 {
cc.Registry = rc.getRegistryIds()
}
for _, reference := range cc.References {
if err := reference.Init(rc); err != nil {
return err
}
}
if err := defaults.Set(cc); err != nil {
return err
}
if err := verify(cc); err != nil {
return err
}
cc.rootConfig = rc
return nil
}
func (cc *ConsumerConfig) Load() {
for key, ref := range cc.References {
if ref.Generic != "" {
genericService := generic.NewGenericService(key)
SetConsumerService(genericService)
}
rpcService := GetConsumerService(key)
if rpcService == nil {
logger.Warnf("%s does not exist!", key)
continue
}
ref.id = key
ref.Refer(rpcService)
ref.Implement(rpcService)
}
// wait for invoker is available, if wait over default 3s, then panic
var count int
for {
checkok := true
for _, refconfig := range cc.References {
if (refconfig.Check != nil && *refconfig.Check) ||
(refconfig.Check == nil && cc.Check) ||
(refconfig.Check == nil) { // default to true
if refconfig.invoker != nil && !refconfig.invoker.IsAvailable() {
checkok = false
count++
if count > maxWait {
errMsg := fmt.Sprintf("Request timed out, please check configuration, Failed to check the status of the service %v. No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)
logger.Error(errMsg)
panic(errMsg)
}
time.Sleep(time.Second * 1)
break
}
if refconfig.invoker == nil {
logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", refconfig.InterfaceName)
}
}
}
if checkok {
break
}
}
}
// SetConsumerConfig sets consumerConfig by @c
func SetConsumerConfig(c ConsumerConfig) {
rootConfig.Consumer = &c
}
// ConsumerInit loads config file to init consumer config
func ConsumerInit(confConFile string) error {
//if confConFile == "" {
// return perrors.Errorf("applicationConfig configure(consumer) file name is nil")
//}
//consumerConfig = &ShutdownConfig{}
//fileStream, err := yaml.UnmarshalYMLConfig(confConFile, consumerConfig)
//if err != nil {
// return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
//}
//consumerConfig.fileStream = bytes.NewBuffer(fileStream)
//// 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.RequestTimeout >= time.Duration(MaxWheelTimeSpan) {
// return perrors.WithMessagef(err, "request_timeout %s should be less than %s",
// consumerConfig.Request_Timeout, time.Duration(MaxWheelTimeSpan))
// }
//}
//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.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)
// }
//}
//if consumerConfig.ConfigCenterConfig != nil {
// consumerConfig.SetFatherConfig(consumerConfig)
// if err = consumerConfig.startConfigCenter((*consumerConfig).BaseConfig); err != nil {
// return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
// }
// consumerConfig.fresh()
//}
return nil
}
func NewEmptyConsumerConfig() *ConsumerConfig {
newConsumerConfig := &ConsumerConfig{
//Registries: make(map[string]*RegistryConfig, 8),
References: make(map[string]*ReferenceConfig, 8),
ConnectTimeout: "3s",
RequestTimeout: "3s",
Check: true,
}
return newConsumerConfig
}
// NewConsumerConfig returns ConsumerConfig with @opts
func NewConsumerConfig(opts ...ConsumerConfigOpt) *ConsumerConfig {
newConfig := NewEmptyConsumerConfig()
for _, v := range opts {
v(newConfig)
}
return newConfig
}
///////////////////////////////////// consumer config api
// ConsumerConfigOpt is the options to init ConsumerConfig
type ConsumerConfigOpt func(config *ConsumerConfig) *ConsumerConfig
// GetConsumerInstance returns ConsumerConfig with @opts
func GetConsumerInstance(opts ...ConsumerConfigOpt) *ConsumerConfig {
cc := &ConsumerConfig{
References: make(map[string]*ReferenceConfig, 8),
Check: true,
}
for _, opt := range opts {
opt(cc)
}
return cc
}
// WithRootConfig returns ConsumerConfigOpt with given @rootConfig
func WithRootConfig(rootConfig *RootConfig) ConsumerConfigOpt {
return func(config *ConsumerConfig) *ConsumerConfig {
config.rootConfig = rootConfig
return config
}
}
// WithConsumerReferenceConfig returns ConsumerConfigOpt with
func WithConsumerReferenceConfig(referenceKey string, refConfig *ReferenceConfig) ConsumerConfigOpt {
return func(config *ConsumerConfig) *ConsumerConfig {
config.References[referenceKey] = refConfig
return config
}
}
// WithConsumerConnTimeout returns ConsumerConfigOpt with given consumer conn @timeout
func WithConsumerConnTimeout(timeout string) ConsumerConfigOpt {
return func(config *ConsumerConfig) *ConsumerConfig {
config.ConnectTimeout = timeout
return config
}
}
// WithConsumerRequestTimeout returns ConsumerConfigOpt with given consumer request @timeout
func WithConsumerRequestTimeout(timeout string) ConsumerConfigOpt {
return func(config *ConsumerConfig) *ConsumerConfig {
config.RequestTimeout = timeout
return config
}
}
// WithConsumerConfigCheck returns ConsumerConfigOpt with given @check flag
func WithConsumerConfigCheck(check bool) ConsumerConfigOpt {
return func(config *ConsumerConfig) *ConsumerConfig {
config.Check = check
return config
}
}