Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
commons
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DevOps
commons
Commits
e652aa0b
Commit
e652aa0b
authored
Dec 07, 2017
by
ag
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat : graceful shutdown & base destroy
parent
622760e3
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
362 additions
and
6 deletions
+362
-6
pom.xml
pom.xml
+17
-1
BaseDestroyHandler.java
.../java/cn/quantgroup/tech/shutdown/BaseDestroyHandler.java
+34
-0
DefaultSignalHandler.java
...ava/cn/quantgroup/tech/shutdown/DefaultSignalHandler.java
+46
-0
GracefulShutdownAutoConfiguration.java
...down/configuration/GracefulShutdownAutoConfiguration.java
+98
-0
GracefulShutdownProperties.java
.../tech/shutdown/properties/GracefulShutdownProperties.java
+21
-0
Shutdown.java
...in/java/cn/quantgroup/tech/shutdown/service/Shutdown.java
+14
-0
TomcatShutdown.java
...a/cn/quantgroup/tech/shutdown/service/TomcatShutdown.java
+57
-0
UndertowShutdown.java
...cn/quantgroup/tech/shutdown/service/UndertowShutdown.java
+30
-0
UndertowShutdownHandlerWrapper.java
...tech/shutdown/wrapper/UndertowShutdownHandlerWrapper.java
+38
-0
IDGenerator.java
src/main/java/cn/quantgroup/tech/util/IDGenerator.java
+5
-5
RedisUtils.java
src/main/java/cn/quantgroup/tech/util/RedisUtils.java
+2
-0
No files found.
pom.xml
View file @
e652aa0b
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
<modelVersion>
4.0.0
</modelVersion>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
cn.quantgroup
</groupId>
<groupId>
cn.quantgroup
</groupId>
<artifactId>
commons
</artifactId>
<artifactId>
commons
</artifactId>
<version>
0.0.
2
</version>
<version>
0.0.
3
</version>
<packaging>
jar
</packaging>
<packaging>
jar
</packaging>
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
<dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
<optional>
true
</optional>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.google.guava
</groupId>
<groupId>
com.google.guava
</groupId>
...
@@ -45,6 +46,21 @@
...
@@ -45,6 +46,21 @@
<artifactId>
lombok
</artifactId>
<artifactId>
lombok
</artifactId>
<version>
1.16.16
</version>
<version>
1.16.16
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-tomcat
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-undertow
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-amqp
</artifactId>
<optional>
true
</optional>
</dependency>
</dependencies>
</dependencies>
<!-- 部署时往公司私服上发包, 可以在网址上找到 其他项目引入该包的需要的 XML -->
<!-- 部署时往公司私服上发包, 可以在网址上找到 其他项目引入该包的需要的 XML -->
...
...
src/main/java/cn/quantgroup/tech/shutdown/BaseDestroyHandler.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils
;
import
org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.Lifecycle
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PreDestroy
;
@Slf4j
@Component
public
class
BaseDestroyHandler
{
@Autowired
private
ApplicationContext
applicationContext
;
@PreDestroy
private
void
stopRedisSub
()
{
// context.getBean(RedisMessageListenerContainer.)
log
.
info
(
"redis stopped"
);
}
@PreDestroy
private
void
stopRabbitMQ
()
{
RabbitListenerEndpointRegistry
rabbitListenerEndpointRegistry
=
applicationContext
.
getBean
(
RabbitListenerConfigUtils
.
RABBIT_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME
,
RabbitListenerEndpointRegistry
.
class
);
rabbitListenerEndpointRegistry
.
getListenerContainers
().
forEach
(
Lifecycle:
:
stop
);
log
.
info
(
"MQ listener stopped"
);
}
}
src/main/java/cn/quantgroup/tech/shutdown/DefaultSignalHandler.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
;
import
cn.quantgroup.tech.shutdown.properties.GracefulShutdownProperties
;
import
cn.quantgroup.tech.shutdown.service.Shutdown
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.context.ApplicationContext
;
import
sun.misc.Signal
;
import
sun.misc.SignalHandler
;
/**
* 默认的停止信号接收处理.
*
* @author ag
*/
@Slf4j
public
class
DefaultSignalHandler
implements
SignalHandler
{
private
ApplicationContext
context
;
public
DefaultSignalHandler
(
ApplicationContext
context
)
{
this
.
context
=
context
;
}
@Override
public
void
handle
(
Signal
signal
)
{
String
applicationName
=
context
.
getApplicationName
();
log
.
info
(
"开始执行停止{}服务"
,
applicationName
);
GracefulShutdownProperties
bean
=
context
.
getBean
(
GracefulShutdownProperties
.
class
);
try
{
context
.
getBean
(
Shutdown
.
class
).
shutdown
(
bean
.
getTimeout
());
log
.
info
(
"servlet container 停止接收请求"
);
}
catch
(
InterruptedException
e
)
{
}
Thread
.
getAllStackTraces
().
forEach
((
thread
,
stackTraceElements
)
->
{
if
(!
thread
.
isDaemon
())
{
//如果中断 daemon 线程, 会导致 PreDestroy 方法不执行,
//如果不中断 non-daemon 线程, 会导致无法 exit(0).
log
.
debug
(
"中断正在进行的 non-daemon 线程: {} ; {}"
,
thread
.
getId
(),
thread
.
getName
());
thread
.
interrupt
();
}
});
log
.
info
(
"{} 即将执行 @PreDestroy 方法"
,
applicationName
);
System
.
exit
(
0
);
}
}
src/main/java/cn/quantgroup/tech/shutdown/configuration/GracefulShutdownAutoConfiguration.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
configuration
;
import
cn.quantgroup.tech.shutdown.properties.GracefulShutdownProperties
;
import
cn.quantgroup.tech.shutdown.service.TomcatShutdown
;
import
cn.quantgroup.tech.shutdown.service.UndertowShutdown
;
import
cn.quantgroup.tech.shutdown.wrapper.UndertowShutdownHandlerWrapper
;
import
io.undertow.Undertow
;
import
org.apache.catalina.startup.Tomcat
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration
;
import
org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer
;
import
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
;
import
org.springframework.boot.context.embedded.undertow.UndertowDeploymentInfoCustomizer
;
import
org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
javax.servlet.Servlet
;
/**
* This configuration class will be picked up by Spring Boot's auto configuration capabilities as soon as it's
* on the classpath.
*/
@Configuration
@ConditionalOnProperty
(
prefix
=
"shutdown.graceful"
,
name
=
"enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
true
)
@EnableConfigurationProperties
(
GracefulShutdownProperties
.
class
)
@Import
(
EmbeddedServletContainerAutoConfiguration
.
BeanPostProcessorsRegistrar
.
class
)
public
class
GracefulShutdownAutoConfiguration
{
/**
* Configuration for Tomcat.
*/
@Configuration
@ConditionalOnClass
({
Servlet
.
class
,
Tomcat
.
class
})
public
static
class
EmbeddedTomcat
{
@Bean
public
TomcatShutdown
tomcatShutdown
()
{
return
new
TomcatShutdown
();
}
/**
* Customise the tomcat factory.
*
* @return an EmbeddedServletContainerCustomizer
*/
@Bean
public
EmbeddedServletContainerCustomizer
tomcatCustomizer
()
{
return
container
->
{
if
(
container
instanceof
TomcatEmbeddedServletContainerFactory
)
{
((
TomcatEmbeddedServletContainerFactory
)
container
).
addConnectorCustomizers
(
tomcatShutdown
());
}
};
}
}
/**
* Configuration for Undertow.
*/
@Configuration
@ConditionalOnClass
({
Servlet
.
class
,
Undertow
.
class
})
public
static
class
EmbeddedUndertow
{
@Bean
public
UndertowShutdown
undertowShutdown
()
{
return
new
UndertowShutdown
();
}
/**
* Customise the undertow factory.
*
* @return an EmbeddedServletContainerCustomizer
*/
@Bean
public
EmbeddedServletContainerCustomizer
undertowCustomizer
()
{
return
container
->
{
if
(
container
instanceof
UndertowEmbeddedServletContainerFactory
)
{
((
UndertowEmbeddedServletContainerFactory
)
container
).
addDeploymentInfoCustomizers
(
undertowDeploymentInfoCustomizer
());
}
};
}
@Bean
public
UndertowDeploymentInfoCustomizer
undertowDeploymentInfoCustomizer
()
{
return
deploymentInfo
->
deploymentInfo
.
addOuterHandlerChainWrapper
(
undertowShutdownHandlerWrapper
());
}
@Bean
public
UndertowShutdownHandlerWrapper
undertowShutdownHandlerWrapper
()
{
return
new
UndertowShutdownHandlerWrapper
();
}
}
}
src/main/java/cn/quantgroup/tech/shutdown/properties/GracefulShutdownProperties.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
properties
;
import
lombok.Getter
;
import
lombok.Setter
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
/**
* Global graceful shutdown properties.
*
* @author Corentin Azelart
*/
@Getter
@Setter
@ConfigurationProperties
(
prefix
=
"shutdown.graceful"
)
public
class
GracefulShutdownProperties
{
/**
* The timeout before force shutdown. TimeUnit.Second
*/
private
Integer
timeout
=
10
;
}
src/main/java/cn/quantgroup/tech/shutdown/service/Shutdown.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
service
;
/**
* Shutdown service.
*/
public
interface
Shutdown
{
/**
* Perform shutdown.
* @param delay is delay to force
* @throw InterruptedException if we have an interruption
*/
void
shutdown
(
Integer
delay
)
throws
InterruptedException
;
}
src/main/java/cn/quantgroup/tech/shutdown/service/TomcatShutdown.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
service
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.catalina.connector.Connector
;
import
org.apache.tomcat.util.threads.ThreadPoolExecutor
;
import
org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.TimeUnit
;
/**
* Perform a tomcat shutdown.
*/
@Slf4j
public
class
TomcatShutdown
implements
Shutdown
,
TomcatConnectorCustomizer
{
/**
* Implementation of a Coyote connector.
*/
private
volatile
Connector
connector
;
/**
* Perform a shutdown
*
* @param delay is delay to force is the delay before perform a force shutdown
* @throws InterruptedException if we have an exception
*/
@Override
public
void
shutdown
(
Integer
delay
)
throws
InterruptedException
{
// Used to properly handle the work queue.
final
Executor
executor
=
connector
.
getProtocolHandler
().
getExecutor
();
final
ThreadPoolExecutor
threadPoolExecutor
=
(
ThreadPoolExecutor
)
executor
;
/*
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
*/
threadPoolExecutor
.
shutdown
();
// We wait after the end of the current requests
if
(!
threadPoolExecutor
.
awaitTermination
(
delay
,
TimeUnit
.
SECONDS
))
{
log
.
warn
(
"Tomcat thread pool did not shut down gracefully within "
+
delay
+
" second(s). Proceeding with force shutdown"
);
}
else
{
log
.
debug
(
"Tomcat thread pool is empty, we stop now"
);
}
}
/**
* Set connector.
*
* @param connector is the catalina connector.
*/
@Override
public
void
customize
(
final
Connector
connector
)
{
this
.
connector
=
connector
;
}
}
src/main/java/cn/quantgroup/tech/shutdown/service/UndertowShutdown.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
service
;
import
cn.quantgroup.tech.shutdown.wrapper.UndertowShutdownHandlerWrapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
/**
* Undertow shutdown.
*/
@Slf4j
public
class
UndertowShutdown
implements
Shutdown
{
/**
* The wrapper for manual commands.
*/
@Autowired
private
UndertowShutdownHandlerWrapper
undertowShutdownHandlerWrapper
;
/**
* Perform shutdown.
*
* @param delay is delay to force
* @throw InterruptedException if we have an interruption
*/
@Override
public
void
shutdown
(
Integer
delay
)
throws
InterruptedException
{
undertowShutdownHandlerWrapper
.
getGracefulShutdownHandler
().
shutdown
();
undertowShutdownHandlerWrapper
.
getGracefulShutdownHandler
().
awaitShutdown
(
delay
*
1000
);
}
}
src/main/java/cn/quantgroup/tech/shutdown/wrapper/UndertowShutdownHandlerWrapper.java
0 → 100644
View file @
e652aa0b
package
cn
.
quantgroup
.
tech
.
shutdown
.
wrapper
;
import
io.undertow.server.HandlerWrapper
;
import
io.undertow.server.HttpHandler
;
import
io.undertow.server.handlers.GracefulShutdownHandler
;
/**
* Undertow handler wrapper.
*/
public
class
UndertowShutdownHandlerWrapper
implements
HandlerWrapper
{
/**
* graceful shutdown handler.
*/
private
GracefulShutdownHandler
gracefulShutdownHandler
;
/**
* Wrapper.
* @param handler is the http handler from chain.
* @return the Undertown shutdown handler.
*/
@Override
public
HttpHandler
wrap
(
final
HttpHandler
handler
)
{
if
(
gracefulShutdownHandler
==
null
)
{
this
.
gracefulShutdownHandler
=
new
GracefulShutdownHandler
(
handler
);
}
return
gracefulShutdownHandler
;
}
/**
* Return the graceful shutdown handler to perform manual command : pause/shutdown.
* @return the shutdown handler.
*/
public
GracefulShutdownHandler
getGracefulShutdownHandler
()
{
return
gracefulShutdownHandler
;
}
}
src/main/java/cn/quantgroup/tech/util/IDGenerator.java
View file @
e652aa0b
...
@@ -4,10 +4,10 @@ import com.google.common.cache.CacheBuilder;
...
@@ -4,10 +4,10 @@ import com.google.common.cache.CacheBuilder;
import
com.google.common.cache.CacheLoader
;
import
com.google.common.cache.CacheLoader
;
import
com.google.common.cache.LoadingCache
;
import
com.google.common.cache.LoadingCache
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
...
@@ -30,11 +30,11 @@ import java.util.concurrent.locks.ReentrantLock;
...
@@ -30,11 +30,11 @@ import java.util.concurrent.locks.ReentrantLock;
* @author zhiguo.liu
* @author zhiguo.liu
* @date 2017/5/18
* @date 2017/5/18
*/
*/
@Component
@Slf4j
@Slf4j
@Component
@ConditionalOnBean
(
RedisTemplate
.
class
)
public
class
IDGenerator
{
public
class
IDGenerator
{
private
static
final
String
REDIS_WORK_ID_KEY
=
"GLOBAL:WORK:ID:"
;
private
static
final
String
REDIS_WORK_ID_KEY
=
"GLOBAL:WORK:ID:"
;
private
static
final
String
ID_FORMAT
=
"yyyyMMddHHmmss"
;
private
static
final
String
ID_FORMAT
=
"yyyyMMddHHmmss"
;
...
@@ -72,7 +72,6 @@ public class IDGenerator {
...
@@ -72,7 +72,6 @@ public class IDGenerator {
static
{
static
{
Date
now
=
new
Date
();
Date
now
=
new
Date
();
MAX_TIME_SECOND
=
now
.
getTime
()
/
1000
;
MAX_TIME_SECOND
=
now
.
getTime
()
/
1000
;
}
}
private
static
LoadingCache
cache
=
CacheBuilder
.
newBuilder
()
private
static
LoadingCache
cache
=
CacheBuilder
.
newBuilder
()
...
@@ -95,6 +94,7 @@ public class IDGenerator {
...
@@ -95,6 +94,7 @@ public class IDGenerator {
@PostConstruct
@PostConstruct
public
void
init
()
{
public
void
init
()
{
log
.
info
(
"test Init id generator"
);
int
workerId
=
(
int
)
(
redis
.
opsForValue
().
increment
(
REDIS_WORK_ID_KEY
+
DATA_CENTER_ID
,
1
)
%
MAX_WORK_ID
);
int
workerId
=
(
int
)
(
redis
.
opsForValue
().
increment
(
REDIS_WORK_ID_KEY
+
DATA_CENTER_ID
,
1
)
%
MAX_WORK_ID
);
WORKER_ID_STR
=
String
.
format
(
"%04d"
,
workerId
);
WORKER_ID_STR
=
String
.
format
(
"%04d"
,
workerId
);
DATA_CENTER_STR
=
String
.
format
(
"%03d"
,
DATA_CENTER_ID
);
DATA_CENTER_STR
=
String
.
format
(
"%03d"
,
DATA_CENTER_ID
);
...
...
src/main/java/cn/quantgroup/tech/util/RedisUtils.java
View file @
e652aa0b
...
@@ -6,6 +6,8 @@ import org.springframework.data.redis.core.RedisTemplate;
...
@@ -6,6 +6,8 @@ import org.springframework.data.redis.core.RedisTemplate;
import
redis.clients.jedis.Jedis
;
import
redis.clients.jedis.Jedis
;
/**
/**
* 目前只写了一个锁, 后面可能还有其他的 Redis 工具类组合
*
* @author zhiguo.liu
* @author zhiguo.liu
* @date 2017/7/28
* @date 2017/7/28
*/
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment