diff --git a/common/constant/key.go b/common/constant/key.go index 122b8e50563ee5d21f7c9a07abe7c1f58a83970a..a275c6135f52e7feb3b0d931e6e1988153eaa1c0 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -114,6 +114,7 @@ const ( ProtocolConfigPrefix = "dubbo.protocols." ProviderConfigPrefix = "dubbo.provider." ConsumerConfigPrefix = "dubbo.consumer." + ShutdownConfigPrefix = "dubbo.shutdown." ) const ( diff --git a/config/base_config_test.go b/config/base_config_test.go index 6dc3749e55f7efbfb1177079f613360cd0d4cc33..3684437d360d09fd82ac93db706edd54dac961d5 100644 --- a/config/base_config_test.go +++ b/config/base_config_test.go @@ -39,6 +39,7 @@ func Test_refresh(t *testing.T) { mockMap["dubbo.com.MockService.MockService.GetUser.retries"] = "10" mockMap["dubbo.consumer.check"] = "false" mockMap["dubbo.application.name"] = "dubbo" + mockMap["dubbo.shutdown.timeout"] = "12s" config.GetEnvInstance().UpdateExternalConfigMap(mockMap) @@ -113,6 +114,13 @@ func Test_refresh(t *testing.T) { }, }, }, + ShutdownConfig: &ShutdownConfig{ + Timeout: "12s", + StepTimeout: "2s", + RejectRequestHandler: "mock", + RejectRequest: false, + RequestsFinished: false, + }, } c.SetFatherConfig(father) diff --git a/config/graceful_shutdown.go b/config/graceful_shutdown.go index eeb559b785b954d2178e09a03229fc1b87de6507..bbc7e64a7ab3b2a80f02c84514d105670ab66d3a 100644 --- a/config/graceful_shutdown.go +++ b/config/graceful_shutdown.go @@ -79,24 +79,6 @@ func GracefulShutdownInit() { }() } -func totalTimeout() time.Duration { - var providerShutdown time.Duration = 0 - if providerConfig != nil && providerConfig.ShutdownConfig != nil { - providerShutdown = providerConfig.ShutdownConfig.GetTimeout() - } - - var consumerShutdown time.Duration = 0 - if consumerConfig != nil && consumerConfig.ShutdownConfig != nil { - consumerShutdown = consumerConfig.ShutdownConfig.GetTimeout() - } - - var timeout = providerShutdown - if consumerShutdown > providerShutdown { - timeout = consumerShutdown - } - return timeout -} - func BeforeShutdown() { destroyAllRegistries() @@ -104,6 +86,7 @@ func BeforeShutdown() { // The value of configuration depends on how long the clients will get notification. waitAndAcceptNewRequests() + time.Sleep(1 * time.Minute) // reject the new request, but keeping waiting for accepting requests waitForReceivingRequests() @@ -116,7 +99,7 @@ func BeforeShutdown() { // If this application is not the consumer, it will do nothing destroyConsumerProtocols() - logger.Infof("Graceful shutdown --- Execute the custom callbacks.") + logger.Info("Graceful shutdown --- Execute the custom callbacks.") customCallbacks := extension.GetAllCustomShutdownCallbacks() for callback := customCallbacks.Front(); callback != nil; callback = callback.Next() { callback.Value.(func())() @@ -124,7 +107,7 @@ func BeforeShutdown() { } func destroyAllRegistries() { - logger.Infof("Graceful shutdown --- Destroy all registries. ") + logger.Info("Graceful shutdown --- Destroy all registries. ") registryProtocol := extension.GetProtocol(constant.REGISTRY_KEY) registryProtocol.Destroy() } @@ -216,3 +199,21 @@ func waitingProcessedTimeout(shutdownConfig *ShutdownConfig) { time.Sleep(10 * time.Millisecond) } } + +func totalTimeout() time.Duration { + var providerShutdown time.Duration = 0 + if providerConfig != nil && providerConfig.ShutdownConfig != nil { + providerShutdown = providerConfig.ShutdownConfig.GetTimeout() + } + + var consumerShutdown time.Duration = 0 + if consumerConfig != nil && consumerConfig.ShutdownConfig != nil { + consumerShutdown = consumerConfig.ShutdownConfig.GetTimeout() + } + + var timeout = providerShutdown + if consumerShutdown > providerShutdown { + timeout = consumerShutdown + } + return timeout +} diff --git a/config/graceful_shutdown_config.go b/config/graceful_shutdown_config.go index d7d21c1499af3a8e362d8b23456899c0938f4001..9077752ce27b5480dc5a96d34a5f63e838003c26 100644 --- a/config/graceful_shutdown_config.go +++ b/config/graceful_shutdown_config.go @@ -21,6 +21,7 @@ import ( "time" ) import ( + "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/common/logger" ) @@ -55,6 +56,10 @@ type ShutdownConfig struct { RequestsFinished bool } +func (config *ShutdownConfig) Prefix() string { + return constant.ShutdownConfigPrefix +} + func (config *ShutdownConfig) GetTimeout() time.Duration { result, err := time.ParseDuration(config.Timeout) if err != nil { diff --git a/registry/zookeeper/listener.go b/registry/zookeeper/listener.go index 67479c4436279782b2fdfffadfcafbe50a708e1b..5a4cc2c66e506360c02b9289f0606692ac168a23 100644 --- a/registry/zookeeper/listener.go +++ b/registry/zookeeper/listener.go @@ -109,7 +109,13 @@ func (l *RegistryConfigurationListener) Next() (*registry.ServiceEvent, error) { } } func (l *RegistryConfigurationListener) Close() { - l.registry.wg.Done() + if l.registry.IsAvailable() { + /** + * if the registry is not available, it means that the registry has been destroy + * so we don't need to call Done(), or it will cause the negative count panic for registry.wg + */ + l.registry.wg.Done() + } } func (l *RegistryConfigurationListener) valid() bool { diff --git a/registry/zookeeper/registry.go b/registry/zookeeper/registry.go index 682b9fe0cfca08aa69ad8842bc856aeb252ae20e..29ae51d44f3691807cbc74912290ba141d1f5d47 100644 --- a/registry/zookeeper/registry.go +++ b/registry/zookeeper/registry.go @@ -173,14 +173,9 @@ func (r *zkRegistry) GetUrl() common.URL { } func (r *zkRegistry) Destroy() { - /** - * Don't r.listener.Close() - * here we don't close the listener because - * the listener will be close in Subscribe(). - * We can not close it here. If we do that, - * a negative count error of r.wg will occur because - * we close the listener twice. - */ + if r.configListener != nil { + r.configListener.Close() + } close(r.done) r.wg.Wait() r.closeRegisters()