云日志服务后端系统如何做到平滑停机

举报
订单王 发表于 2017/11/17 10:07:44 2017/11/17
【摘要】 在日志服务中,我们使用了 kafka 作为消息中间件,日志数据会首先暂存在消息队列中,然后消费者再根据后端业务的处理能力,逐步消费这些日志数据。采用消息队列,能够做到前后端业务解耦,对外的接口可以提供高吞吐量,内部业务系统可以根据实际处理能力,对消息进行消费处理。在服务端,我们的消费者从 kafka 中取出消息,然后累积至一定的数量,再批量提交至服务端的业务系统。不同的业务系统,批量处理能力不同,

在日志服务中我们使用了 kafka 作为消息中间件日志数据会首先暂存在消息队列中然后消费者再根据后端业务的处理能力,逐步消费这些日志数据

采用消息队列,能够做到前后端业务解耦,对外的接口可以提供高吞吐量,内部业务系统可以根据实际处理能力,对消息进行消费处理。

在服务端,我们的消费者从 kafka 中取出消息,然后累积至一定的数量再批量提交至服务端的业务系统。不同的业务系统,批量处理能力不同,每个业务系统会建立各自的线程池与kafka交互。

Image 21.png

kafka 与我们的业务系统对接采用典型的分布式部署方式kafka 采用三节点部署组成集群,业务系统每个集群至少为两个节点,避免单点故障。由于在业务系统中,我们缓存了部分数据,因此面临一个重要的问题就是:如何在系统升级时,重启应用做到内存中的数据不丢失?

解决的方式很简单,在程序启动的时候,注册shutdown hook,通过该shutdown hook,程序就可以接收进程停止的信号。在接收到该信号之后,通知业务线程,不再处理新的请求或者接收新的事件,并把内存中缓存的数据消费处理完就可以了。

Image 23.png

在这个处理环节中,我们在程序中创建了一个“生命周期管理器,所有的业务线程在启动的时候,首先将自己注册到管理器中,然后才进行业务处理(事件监听、接收请求等)。

当要进行程序停止(升级操作)时,通过外部的启停脚本,给该进程发送TERM信号(kill <pid> / kill –TERM <pid>)。

Hook线程接收到该信号之后,通知生命周期管理器,然后等待其处理结束。注意:这里必须等待生命周期管理器处理完成,否则程序会立即结束。

在管理器里,我们最开始是顺序遍历所有的业务线程,调用业务线程的stop方法,通过但是由于业务线程量比较大,如果等待所有的线程结束,整体时间是不可控的。

改进后的方案是,在顺序遍历所有业务线程时,new新的线程用于执行原有业务线程的stop方法,这种做法相当于并发的将stop命令通知到所有的业务线程。在下发stop命令的同时,我们传入一个计数器给该业务线程,在业务线程的stop方法结束时,该计数器减1,计数器的大小是所有业务线程的个数,这样当该计数器为0的时候,可以认为所有的业务线程已经正常停止,就可以真正的停止程序。

以上是我们服务端的平滑停机的一些实践由于经验有限还希望大家多多提意见


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。