本文从三个方面阐述优雅关机相关方案:
1. web项目。
采用spring boot启动的项目,可以参考Spring boot 2.0 之优雅停机中的内容进行代码修改。但是这么做是远远不足的,该方法实际是等待web I/O线程池中的线程关闭后才关机,一般设置等待一分钟后关闭。kill -15 触发,之后发来的请求都会成为网络超时。该方案不足原因是如果在超大量的请求情况下,前端将会在1min内产生大量的网络超时,一般实际不可接受。实际工作中采用nginx,或f5来控制前端请求。对尚在处理中的请求等待全部处理完以后才关闭线程。新到来的请求使用新的线程和新的配置。nginx相关配置参见:平滑更新nginx二进制
2. dubbo项目。
dubbo本身网上具有优雅关闭的相关文章很多。但是,如果作为一个provider方,需要考虑的不仅仅是dubbo。如果在本身是web项目,service本身去调用B项目。调用方式采用dubbo。调用后有dao层相关逻辑。这里dubbo的优雅关闭,确实可以做到等待dubbo返回后才关机,但是,这里没有对dao层相关线程池做优雅关机。因此dao层的逻辑其实根本没有走到。针对这种情况,实际采用修改dubbo的调用权值来处理的。
首先点击,
服务治理-》服务,找到对应的服务,点击。然后到图示界面。首先点击倍权或半权。然后点击动态配置tab页。
在动态配置中点击编辑。将weight的参数值改为0.点击保存。此时,该服务在动态配置中状态会显示为已禁用。
3. 点击动态配置tab页中ip对应的操作中点击启用。此时,权值就会修改为0.
这样修改成功后,将不会调用该ip地址。因此,该ip地址等待1min左右,就可以做到关机,项目上线。
这样做到优雅停机。
3. kafka项目
kafka可以分为两种 项目-》kafka 和 kafka-》项目。
对项目调用kafka的情况,一般正常优雅停机状态下,消息会发送到kafka,这种项目一般划归到上文1,2两种情况处理即可。
对kafka-》项目的情况,如果是手动提交offset。没有问题。这里大致阐述下我看了一会对kafka的wakeup方法的理解。个人感觉
和优雅停机好像关系也不大,真需要停机情况,只有kafka-》项目时,直接kill - 9即可。
对consume逻辑,方法如下:
private ConsumerRecords<K, V> poll(final long timeoutMs, final boolean includeMetadataInTimeout) {
...
do{
client.maybeTriggerWakeup();
...
record = selector.select(timeout);
if(record != null){ //................1
//调用业务处理逻辑代码
consume(record);
}
}while (elapsedTime < timeoutMs);
wakeup方法,只做了两件事。
1.设置wakeup值为true。
2.this.nioSelector.wakeup();
设置为true可以让client.maybeTriggerWakeup();方法抛出异常。this.nioSelector.wakeup();可以让seletctor.select(timeout)语句
直接返回。
都无法保证在执行kill -15 的时候,正处在consume(record)之前,而在selector.select(timeout)返回有数据的情况的代码之后。
也就是代码中标记为1的那个地方的代码在执行的时候。此时还是可以关闭掉项目,同时,如果自动提交offset则
消息的处理代码逻辑consume(record)方法尚未执行。
因此,wakeup并不能保证自动提交的情况下处理逻辑不丢失。