vipyxc-byte commented on issue #3153: URL: https://github.com/apache/dubbo-go/issues/3153#issuecomment-3775913343
> Could you provide a reproducible code demo? I failed to reproduce this bug. 抱歉,因公司规范,无法直接提供代码仓库或者压缩包,只能以这种形式提供,代码在下面。 # 背景 k8s集群下多次发布、重启服务提供者会导致泛化调用报 session Already Closed,之后 dubbo-go 一直连接旧地址,这是最初的问题。 所以我认为在 session Already Closed 时主动销毁 ReferenceConfig 再重新构建可以解决问题。 但是在并发销毁/重新构建 ReferenceConfig 时,偶尔会出现 panic,Alanxtl 无法复现 session Already Closed,但修复了偶发的 panic 问题。 如果你能解决 session Already Closed 问题,我就不用使用我的方案了。 另外我认为重新构建 ReferenceConfig 是合理的操作,不应该出现 panic。以下是 3.3.1 版本仍然存在的 panic。 最初的问题:https://github.com/apache/dubbo-go/issues/2981 现在的问题:https://github.com/apache/dubbo-go/issues/3153 ## 2026-01-05 panic panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x102a668f8] goroutine 3809079 [running]: dubbo.apache.org/dubbo-go/v3/common.(*URL).GetParam(0x0, {0x1045bd638, 0xb}, {0x0, 0x0}) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/common/url.go:608 +0x38 dubbo.apache.org/dubbo-go/v3/cluster/router/tag.(*PriorityRouter).Notify(0x1414fe18c60, {0x140b6945170, 0x1, 0x1}) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/cluster/router/tag/router.go:80 +0x84 dubbo.apache.org/dubbo-go/v3/cluster/router/chain.(*RouterChain).SetInvokers(0x140f6b38720, {0x140b6945170, 0x1, 0x1}) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/cluster/router/chain/chain.go:95 +0x1a4 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).setNewInvokers(0x140b0e65d90) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:344 +0x148 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).refreshInvokers(0x140b0e65d90, 0x1416408ea80) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:241 +0x1b4 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Notify(0x140b0e65d90, 0x1416408ea80) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:219 +0x44 dubbo.apache.org/dubbo-go/v3/registry.(*BaseRegistry).Subscribe(0x14000ab90e0, 0x140b14d61c0, {0x104f49fd0, 0x140b0e65d90}) /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/base_registry.go:354 +0x44c dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Subscribe.func1() /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:167 +0x8c created by dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Subscribe in goroutine 1640288 /Users/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:165 +0x160 ## 2026-01-20 此代码复现 panic panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x1047b1108] goroutine 271982 [running]: dubbo.apache.org/dubbo-go/v3/common.(*URL).GetParam(0x0, {0x105b4f87c, 0x5}, {0x0, 0x0}) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/common/url.go:608 +0x38 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).toGroupInvokers.func1({0x105e3b060, 0x14000ebb700}, {0x105fec1e0, 0x14001a03f20}) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:393 +0xa0 internal/sync.(*HashTrieMap[...]).iter(0x10626b3c0, 0x140012065a0, 0x14001547b58) /Users/yangzhen/dev/go/pkg/mod/golang.org/[email protected]/src/internal/sync/hashtriemap.go:512 +0x1b4 internal/sync.(*HashTrieMap[...]).Range(0x10626b3c0, 0x14001547b58) /Users/yangzhen/dev/go/pkg/mod/golang.org/[email protected]/src/internal/sync/hashtriemap.go:495 +0x84 sync.(*Map).Range(0x14001b99f20, 0x14001547b58) /Users/yangzhen/dev/go/pkg/mod/golang.org/[email protected]/src/sync/hashtriemap.go:115 +0x3c dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).toGroupInvokers(0x1400075b8c0) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:391 +0x148 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).setNewInvokers(0x1400075b8c0) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:340 +0x24 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).refreshInvokers(0x1400075b8c0, 0x14001a0a2a0) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:241 +0x1b4 dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Notify(0x1400075b8c0, 0x14001a0a2a0) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:219 +0x44 dubbo.apache.org/dubbo-go/v3/registry.(*BaseRegistry).Subscribe(0x14000756ea0, 0x14001d981c0, {0x106238250, 0x1400075b8c0}) /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/base_registry.go:354 +0x44c dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Subscribe.func1() /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:167 +0x8c created by dubbo.apache.org/dubbo-go/v3/registry/directory.(*RegistryDirectory).Subscribe in goroutine 271980 /Users/yangzhen/dev/go/pkg/mod/dubbo.apache.org/dubbo-go/[email protected]/registry/directory/directory.go:165 +0x160 # 测试的 java 服务提供者代码 git clone https://gitee.com/yangzhen94/hyperway-dubbo.git jdk11 修改 resources/application.xml 中的 address 地址 # 测试逻辑 1. 初始化 dubbo 服务后启动协程定时 1s 后调用 config.ReferenceConfig#Destroy 2. main 函数中启动多个协程并发调用泛化服务 忽略以下日志,第一个是重新构建 ReferenceConfig 调用服务时出现的,第二个是偶发的可以捕获的 panic 1. dubbo rpc invoke failed: Rpc cluster invoker for com.hyperway.rpc.client.IHelloService on consumer 10.202.161.36 use dubbo version 3.3.1 is now destroyed! can not invoke any more. 2. dubbo rpc invoke panic # 代码 ## dubbo/generic_api_def.go 泛化服务的api结构 ```go package dubbo import ( "time" hessian "github.com/apache/dubbo-go-hessian2" ) type ( GenericApi struct { application string // 所属应用 protocol string // 协议,必须 interfaceName string // 接口名,必须 version string // 版本 group string // 分组 timeout string // 超时时间,注意要带单位,例如:5s retries string // 重试次数 waitForInitSecond time.Duration // 静态注册的dubbo消费者初始化的时间,单位:秒,动态注册的api等待时间是固定值 } Args struct { Method string // 方法名,必需 Names []string // 参数名,非必需 Types []string // 参数类型,必需,java类型参考:JavaType Values []hessian.Object // 参数值,必需 Attachments map[string]string // 附加信息,非必需 } ) // 仅仅缓存dubbogo.yaml中consumer配置的key var readOnlyConsumers map[string]*GenericApi // RefId 返回api的唯一标识 func (ga *GenericApi) RefId() string { return ga.group + "/" + ga.interfaceName + ":" + ga.version } // getConsumerApi 根据dubbogo.yaml中consumer配置的key获取消费者api func getConsumerApi(key string) *GenericApi { return readOnlyConsumers[key] } ``` ## dubbo/generic_load.go 加载泛化服务 ```go package dubbo import ( "context" "fmt" "log" "math/rand" "sync" "sync/atomic" "time" "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/config" "dubbo.apache.org/dubbo-go/v3/config/generic" "dubbo.apache.org/dubbo-go/v3/protocol" "github.com/pkg/errors" ) var t *rpcTransporter type ( rpcTransporter struct { Application *config.ApplicationConfig `validate:"required" yaml:"application" json:"application,omitempty" property:"application"` Registries map[string]*config.RegistryConfig `yaml:"registries" json:"registries" property:"registries"` Logger *config.LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"` // Consumer不参与config.loadReference // 获取registryIds/RequestTimeout/References Consumer *config.ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"` references *referenceCache } // referenceCache 缓存引用配置 referenceCache struct { references map[string]*reference lock *sync.RWMutex // 保证 references 的并发安全 } // reference 引用配置,可以复用 reference struct { lock *sync.Mutex // 保证 rf 的并发安全 lastDestroyAt atomic.Int64 // 上次销毁时间 rf *config.ReferenceConfig // 泛化服务的引用,可以销毁 } rpcService struct { *generic.GenericService *reference } ) func (t *rpcTransporter) loadRpcService(api *GenericApi) (*rpcService, error) { ref := t.references.getReference(api.RefId()) if ref == nil { ref = t.references.loadReference(api.RefId()) } commonRPCService, err := ref.load(api) if err != nil { return nil, err } return &rpcService{ GenericService: commonRPCService.(*generic.GenericService), reference: ref, }, nil } // preloadRPCService 加载RPC服务 func (t *rpcTransporter) preloadRPCService(api *GenericApi) (common.RPCService, error) { ref := t.references.getReference(api.RefId()) if ref == nil { ref = t.references.loadReference(api.RefId()) } load, err := ref.load(api) return load, err } // loadReference 加载引用配置 func (rc *referenceCache) loadReference(refId string) *reference { rc.lock.Lock() defer rc.lock.Unlock() if r, ok := rc.references[refId]; ok { return r } else { r = &reference{ lock: &sync.Mutex{}, lastDestroyAt: atomic.Int64{}, rf: nil, } rc.references[refId] = r return r } } // load 加载泛化服务 func (r *reference) load(api *GenericApi) (common.RPCService, error) { r.lock.Lock() defer r.lock.Unlock() refId := api.RefId() if r.rf != nil { return r.rf.GetRPCService(), nil } if api.protocol == "" { api.protocol = constant.Dubbo } if api.timeout == "" { api.timeout = t.Consumer.RequestTimeout } if api.retries == "" { api.retries = "0" } r.rf = config.NewReferenceConfigBuilder(). SetInterface(api.interfaceName). SetGroup(api.group). SetVersion(api.version). SetRequestTimeout(api.timeout). SetRetries(api.retries). SetProtocol(api.protocol). SetRegistryIDs(t.Consumer.RegistryIDs...). SetGeneric(true). SetSerialization(constant.Hessian2Serialization). SetLoadbalance(constant.LoadBalanceKeyRandom). SetCluster(constant.ClusterKeyFailover). Build() rootConfig := config.GetRootConfig() err := r.rf.Init(rootConfig) if err != nil { return nil, err } // v3.2.0-rc1 refConf.GenericLoad(refId)存在bug,需要手动创建和关联相关的GenericService // v3.3.0 修复了这个bug,直接使用refConf.GenericLoad(refId)即可 // refConf.GenericLoad(refId) // 自维护,所以手动创建和关联GenericService,而且不需要 onfig.SetConsumerService(gs) gs := generic.NewGenericService(refId) r.rf.Refer(gs) r.rf.Implement(gs) // config.SetConsumerService(gs) waitTime := api.waitForInitSecond if waitTime <= 0 { waitTime = 5 * time.Second } timeout, cancel := context.WithTimeout(context.Background(), waitTime) defer cancel() index := 0 end: for { index++ select { case <-timeout.Done(): log.Println("dubbo rpc service load timeout") break end default: b := r.recheck(r.rf.GetInvoker()) if b { log.Printf("dubbo rpc service load success, recheck count: %d\n", index) break end } time.Sleep(1 * time.Second) } } // TODO r.testDestroy(refId) return r.rf.GetRPCService(), nil } // recheck 检查invoker是否可用 func (r *reference) recheck(invoker protocol.Invoker) bool { defer func() { // invoker.IsAvailable 逻辑中可能会有 panic: runtime error: invalid memory address or nil pointer dereference if r := recover(); r != nil { log.Println("generic service not ready, wait for next check") } }() if !invoker.IsAvailable() { return false } return true } // getReference 从缓存中获取 reference func (rc *referenceCache) getReference(refId string) *reference { rc.lock.RLock() defer rc.lock.RUnlock() if r, ok := rc.references[refId]; ok { return r } return nil } // loadConsumer 加载消费者 func (t *rpcTransporter) loadConsumer() error { readOnlyConsumers = make(map[string]*GenericApi) for key, referenceConfig := range t.Consumer.References { api := &GenericApi{ application: t.Application.Name, protocol: referenceConfig.Protocol, interfaceName: referenceConfig.InterfaceName, version: referenceConfig.Version, group: referenceConfig.Group, timeout: referenceConfig.RequestTimeout, retries: referenceConfig.Retries, waitForInitSecond: 5 * time.Second, } if _, err := t.preloadRPCService(api); err != nil { return errors.Wrap(err, "failed to load consumers") } readOnlyConsumers[key] = api } return nil } // destroy 销毁泛化服务,仅作为测试时使用 func (r *reference) destroy() { r.lock.Lock() defer r.lock.Unlock() if r.rf != nil { invoker := r.rf.GetInvoker() r.rf = nil invoker.Destroy() } } // testDestroy 测试定时销毁泛化服务, // Deprecated: 该方法会触发dubbo底层异步协程的panic,导致应用宕机 func (r *reference) testDestroy(refId string) { go func() { random := rand.New(rand.NewSource(time.Now().UnixNano())) delay := random.Intn(6) + 10 delay = 1 sc := time.NewTimer(time.Duration(delay) * time.Second) defer sc.Stop() select { case <-sc.C: fmt.Printf("[DESTROY-%s] %p\n", refId, r.rf) r.destroy() } }() } ``` ## dubbo/generic_invoke.go 调用泛化服务 ```go package dubbo import ( "context" "runtime/debug" "strings" "dubbo.apache.org/dubbo-go/v3/common/constant" _ "dubbo.apache.org/dubbo-go/v3/imports" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) // ProxyInvoke 代理dubbo服务的调用,返回 T 对应的结果 // consumerKey 消费者配置的key // args 请求参数 // return *T T可能为nil // return error 错误信息 // 响应结构使用包装,判断请求成功与否 func ProxyInvoke[T any](ctx context.Context, consumerKey string, args *Args) (*T, error) { api := getConsumerApi(consumerKey) if api == nil { return nil, errors.New("failed to get consumer api for key: " + consumerKey) } if args.Attachments == nil { args.Attachments = make(map[string]string) } result, err := InvokeAndDecoded[T](ctx, api, args) if err != nil { return nil, err } if result == nil { return nil, nil } return result, nil } // Invoke 执行调用 // ctx: 上下文 // api: 泛化调用的API // args: 参数,参数类型的顺序要和接口定义的顺序一致,否则会出现NoSuchMethod,也可能导致NoProvider的错误,dubbo-admin查不到元数据,但实际dubbo服务是存在的 // traceId: 链路追踪 // return any: 泛化调用的结果,可能为nil func Invoke(ctx context.Context, api *GenericApi, args *Args) (resp any, err error) { defer func() { if rec := recover(); rec != nil { // 打印堆栈到标准输出 debug.PrintStack() err = errors.Errorf("dubbo rpc invoke panic: %v\n%s", rec, debug.Stack()) } }() var rpc *rpcService if rpc, err = t.loadRpcService(api); err != nil { return nil, errors.Wrap(err, "failed to load dubbo rpc service") } defer func() { if err != nil { // dubbo3.3.0泛化调用会出现 session Already Closed,之后服务不可用,无法恢复 // 当出现该错误时,销毁引用,下次重新创建 if strings.HasPrefix(err.Error(), "session Already Closed") { rpc.destroy() } err = errors.Wrap(err, "dubbo rpc invoke failed") } }() dubboCtx := dealAttachments(ctx, args) // 泛化调用的接口可能返回nil,例如定义的返回值是void或者返回null // 传递的参数类型和接口定义的参数类型不匹配时报NoSuchMethod的异常 resp, err = rpc.Invoke( dubboCtx, args.Method, args.Types, args.Values, ) if err != nil { return nil, err } return resp, nil } func InvokeAndDecoded[T any](ctx context.Context, api *GenericApi, args *Args) (*T, error) { resp, err := Invoke(ctx, api, args) if err != nil { return nil, err } if resp == nil { return nil, nil } var o T // 当结构体定义的类型和返回数据的类型不匹配时,会报错,例如定义int但返回string // 不支持json字符串的解码 // 不支持基本数据类型的解码 // 当resp为nil时,Decode不会报错 err = mapstructure.Decode(resp, &o) if err != nil { return nil, errors.Wrap(err, "response decode failed") } return &o, nil } // dealAttachments 处理dubbo的附加参数 func dealAttachments(ctx context.Context, args *Args) context.Context { if args.Attachments == nil { args.Attachments = map[string]string{} } return context.WithValue(ctx, constant.AttachmentKey, args.Attachments) } ``` ## dubbo/init.go 初始化dubbo ```go package dubbo import ( "os" "strings" "sync" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/config" "github.com/knadh/koanf" "github.com/knadh/koanf/parsers/json" "github.com/knadh/koanf/parsers/toml" "github.com/knadh/koanf/parsers/yaml" "github.com/knadh/koanf/providers/rawbytes" "github.com/magiconair/properties" "github.com/pkg/errors" ) var ( once sync.Once ) // Init 使用官网的dubbogo.yaml配置文件,但目前不需要环境变量DUBBO_GO_CONFIG_PATH=./conf/dubbogo.yaml func Init() { once.Do(func() { k, err := LoadKoanf("dubbogo.yaml", ".", "yaml") if err != nil { panic(err) } t = &rpcTransporter{ Consumer: &config.ConsumerConfig{}, Application: &config.ApplicationConfig{}, Registries: make(map[string]*config.RegistryConfig), Logger: &config.LoggerConfig{}, references: &referenceCache{ references: make(map[string]*reference), lock: &sync.RWMutex{}, }, } err = k.UnmarshalWithConf(constant.Dubbo, t, koanf.UnmarshalConf{Tag: "yaml"}) if err != nil { panic(err) } rootConfig := config.NewRootConfigBuilder(). SetApplication(t.Application). SetRegistries(t.Registries). SetLogger(t.Logger). Build() if err = config.Load(config.WithRootConfig(rootConfig)); err != nil { panic(err) } err = t.loadConsumer() if err != nil { panic(err) } }) } // LoadKoanf config from file func LoadKoanf(filepath, delim string, suffix string) (*koanf.Koanf, error) { bytes, err := os.ReadFile(filepath) if err != nil { return nil, err } k := koanf.New(delim) switch suffix { case "yaml", "yml": err = k.Load(rawbytes.Provider(bytes), yaml.Parser()) case "json": err = k.Load(rawbytes.Provider(bytes), json.Parser()) case "toml": err = k.Load(rawbytes.Provider(bytes), toml.Parser()) case "properties": err = k.Load(rawbytes.Provider(bytes), Parser()) default: err = errors.Errorf("no support %s file suffix", suffix) } if err != nil { return nil, err } return k, nil } type Properties struct{} func Parser() *Properties { return &Properties{} } // Unmarshal parses the given properties bytes. func (p *Properties) Unmarshal(b []byte) (map[string]any, error) { out := make(map[string]any) if load, err := properties.Load(b, properties.UTF8); err != nil { return nil, err } else { // see viper#unmarshalReader for _, key := range load.Keys() { value, _ := load.Get(key) // recursively build nested maps path := strings.Split(key, ".") lastKey := path[len(path)-1] deepestMap := deepSearch(out, path[0:len(path)-1]) // set innermost value deepestMap[lastKey] = value } return out, nil } } func (p *Properties) Marshal(o map[string]any) ([]byte, error) { return nil, nil } func deepSearch(m map[string]any, path []string) map[string]any { for _, k := range path { m2, ok := m[k] if !ok { // intermediate key does not exist // => create it and continue from there m3 := make(map[string]any) m[k] = m3 m = m3 continue } m3, ok := m2.(map[string]any) if !ok { // intermediate key is a value // => replace with a new map m3 = make(map[string]any) m[k] = m3 } // continue search from here m = m3 } return m } ``` ## mock/mock.go ```go package mock import ( "context" "dubbo-go-demo/dubbo" "fmt" hessian "github.com/apache/dubbo-go-hessian2" ) type ( ResultVO struct { Value *UserVO } // UserVO 用户信息 UserVO struct { ID int64 `json:"id"` Name string `json:"name"` } ) // GetUserVOList 获取UserVO列表数据 func GetUserVOList(ctx context.Context) { args := &dubbo.Args{ Method: "helloList", Types: []string{ "java.util.List", }, Values: []hessian.Object{ []map[string]interface{}{ { "id": 123, "name": "user-123", }, { "id": 456, "name": "user-456", }, }, }, } _, err := dubbo.ProxyInvoke[[]UserVO](ctx, "demo-rpc", args) if err != nil { fmt.Printf("[ERROR-USER-VO-LIST]: %v\n", err) } else { //fmt.Printf("[USER-VO-LIST]: %+v\n", result) } } // GetUserVO 获取UserVO数据 func GetUserVO(ctx context.Context) { args := &dubbo.Args{ Method: "helloUser", Types: []string{"com.hyperway.rpc.client.User"}, Values: []hessian.Object{ map[string]any{ "id": 123, "name": "user-123", }, }, } _, err := dubbo.ProxyInvoke[ResultVO](ctx, "demo-rpc", args) if err != nil { fmt.Printf("[ERROR-USER-VO]: %v\n", err) //} else if result != nil { // fmt.Printf("[USER-VO]: %+v\n", result.Value) } } ``` ## main.go ```go package main import ( "context" "dubbo-go-demo/dubbo" "dubbo-go-demo/mock" "math/rand" "time" ) func main() { dubbo.Init() time.Sleep(3 * time.Second) minMs, maxMs := 100, 1000 // 5个goroutine并发调用dubboCall,每次调用休眠100ms,goroutine要一直运行 for i := 0; i < 150; i++ { go func() { random := rand.New(rand.NewSource(time.Now().UnixNano())) for { // rand.Intn(n) 会返回 [0, n) 的整数,所以这里要加上 min ms := random.Intn(maxMs-minMs+1) + minMs //go mock.GetInteger(context.Background()) go mock.GetUserVO(context.Background()) go mock.GetUserVOList(context.Background()) time.Sleep(time.Duration(ms) * time.Millisecond) } }() } select { case <-time.After(1 * time.Hour): } } ``` ## dubbogo.yaml ```yaml dubbo: application: organization: "demo" name: "demo" owner: "demo" registries: zk: protocol: "zookeeper" timeout: "10s" # address: "127.0.0.1:2181" address: "10.202.244.20:32181" registry-type: "interface" logger: level: "warn" format: "json" driver: "zap" appender: "file" file: name: "dubbo.log" max-size: 5 max-backups: 3 max-age: 3 compress: false consumer: registry-ids: [ "zk" ] request-timeout: "16s" references: demo-rpc: protocol: "dubbo" interface: "com.hyperway.rpc.client.IHelloService" timeout: "6s" retries: "2" registry: "zk" ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
