一个糟糕的决策带来无尽的折磨

一个糟糕的决策带来无尽的折磨

你也时常有这种感觉么?怎么每次迭代都让人感觉很费劲,很疲惫,似乎每次都要对之前的代码进行修改才能满足本次迭代的需求。
整个项目像是一团乱麻一样理不清楚,项目工程给人一次性纸杯的感觉,似乎只能用一次。团队成员只有靠夜以继日的加班,
才能完成本次迭代,同时它的质量并不高,其实就是以量取胜的策略。如果你是一个团队的管理者你需要好好反思一下这究竟
是为什么呢。

一个糟糕的决策缺乏思考,在未来不仅仅会折磨自己也会折磨别人。然后整个团队默默忍受着这种折磨,直到摆烂。

下面分享一个案例,希望大家看了能开心,毕竟当事人真的很痛苦。

在一个项目中包含业务接口,业务类,和Job类,Job类通常是执行一些批处理作业,令人惊讶的是这些类竟然运行在同一个 JVM 中,
这可真是一场灾难。后面会说明这么做的坑在哪里。

现在该如何优雅停机?

现在这些类都运行在同一个 JVM 中该怎么优雅停机呢? 当我被问到这个问题的时候,老实说我也不知道该怎么做。

什么叫优雅停机?

简单的说,就是向应用进程发出停止指令之后,能保证正在执行的业务操作不受影响,直到操作运行完毕之后再停止服务。应用程序接收到停止指令之后,会进行如下操作:

  1. 停止接收新的访问请求
  2. 正在处理的请求,等待请求处理完毕;对于内部正在执行的其他任务,比如定时任务、mq 消费等等,也要等当前正在执行的任务执行完毕,并且不再启动新的任务
  3. 当应用准备关闭的时候,按需向外发出信号,告知其他应用服务准备接手,以保证服务高可用。
  4. 触发 shutdown hook 释放或关闭一些资源。

如果暴力的关闭应用程序,比如通过 kill -9 <pid> 命令强制直接关闭应用程序进程,可能会导致正在执行的任务数据丢失或者错乱,也可能会导致任务所持有的全局资源等不到释放,比如当前任务持有 redis 的锁,并且没有设置过期时间,当任务突然被终止并且没有主动释放锁,会导致其他进程因无法获取锁而不能处理业务。

暴力停机可能导致数据的不一致,例如调用了某个事务性的第三方接口,接口调用已经成功在第三方系统中事务已经成功,但此时暴力停机导致本地事务失败。
这时候就造成了本地数据和第三方数据的不一致。

由于有批处理 Job 可能正在执行,而且这种 Job 执行耗时时间都比较长,可能是几个小时,这时候如果我们使用 kill -15 <pid> 则会等待的时间很长而且是不确定的。
这就导致无法快速的完成发版,为了实现能够快速的发版也只好硬着头皮的 kill -9 <pid> 杀掉进程。

kill -9 与 kill -15

kill :发送指定的信号到相应进程。不指定信号将发送SIGTERM(15)终止指定进程。若仍无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。

使用 kill -l 可以列举所有支持的信号:

当我们使用kill pid时,实际相当于kill -15 pid。也就是说默认信号为15。使用kill -15时,系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该信号后,具体要如何处理自己可以决定。
这时候,应用程序可以选择:

  1. 立即停止程序
  2. 释放响应资源后停止程序
  3. 忽略该信号,继续执行程序

因为kill -15信号只是通知对应的进程要进行"安全、干净的退出",程序接到信号之后,退出前一般会进行一些"准备工作",如资源释放、临时文件清理等等,如果准备工作做完了,再进行程序的终止。
但是,如果在"准备工作"进行过程中,遇到阻塞或者其他问题导致无法成功,那么应用程序可以选择忽略该终止信号。
这也就是为什么我们有的时候使用kill命令是没办法"杀死"应用的原因,因为默认的kill信号是SIGTERM(15),而SIGTERM(15)的信号是可以被阻塞和忽略的。
kill -15相比,kill -9 就相对强硬得多,系统会发出SIGKILL信号,他要求接收到该信号的程序应该立即结束运行,不能被阻塞或者忽略。
所以,kill -9在执行时,应用程序是没有时间进行"准备工作"的,所以这通常会带来一些副作用,数据丢失或者终端无法恢复到正常状态等。

Java应用对SIGTERM信号的处理

Java应用在Linux中是以一个独立进程的形式运行的,Java程序的终止运行基于JVM的关闭实现,JVM关闭方式分为3种:

  1. 正常关闭:当最后一个非守护线程结束或者调用了System.exit或者通过其他特定平台的方法关闭(接收到SIGINT(2)、SIGTERM(15)信号等)
  2. 强制关闭:通过调用Runtime.halt方法或者是在操作系统中强制kill(接收到SIGKILL(9)信号)
  3. 异常关闭:运行中遇到RuntimeException异常等。

JVM 进程在接收到kill -15信号通知的时候,会做一些清理动作的,例如删除临时文件。同时,也提供了hook机制,来让开发者自定义清理动作,对应的方法为:Java.Runtime.addShutdownHook(Thread hook)。我们可以自定义一个shuthook并测试效果:

public class MyShutdownHook {public static void main(String[] args) throws InterruptedException{boolean flag = true;Runtime.getRuntime().addShutdownHook(new Thread(() -> {System.out.println("my hook execute end");}));while (flag) {System.out.println("my app is running");TimeUnit.SECONDS.sleep(3);}System.out.println("main thread execute end");}
}

当使用 kill -9 的时候该 shutdown hook 是不会执行的。

接口响应怎么这么慢没有反应?

接口响应非常的慢,给人的感觉好像服务僵死了一样。这时候你可能会去首先排查网络层面看网络是否畅通,带宽是否被占满,再查查服务器文件句柄数量是否足够,再查查服务器内存是否足够,再查查服务器磁盘是否足够,再查查服务器cpu是否足够,再查查服务器网络是否足够,再查查服务器磁盘是否足够,再查查服务器内存是否足够,再查查服务器cpu是否足够,再查查服务器网络是否足够,再查查服务器磁盘是否足够,再查查服务器
看看服务内存是否被跑满,CPU 使用率是否非常的高等等。当然这些都是有可能发生的,是导致问题现象产生的原因之一。

来看看下图的例子,http 线程都处于 WAITING 状态,而Job线程池中的线程都处于 RUNNABLE 状态。
也就是 Job 和接口请求在争夺资源。谁让它们都运行在同一个 JVM 中呢。

已经不想多说什么了,心有点累…

解决问题

首先我建议先规范工程结构,比如我们有一个订单服务 order-service ,其中包含这几个模块 order-commonorder-facade
order-coreorder-weborder-job ,其中 order-weborder-job 可以作为启动模块,进行单独的部署。
同时它们都可以依赖 order-commonorder-facadeorder-core 模块,很大程度上的解决了代码复用问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

雅思阅读 答题技巧和题型归纳总结 看着一篇就够了

下面给大家介绍一下雅思阅读中常见的十种题型&#xff0c;以及各个题型烤鸭们经常遇到的问题&#xff0c;最后介绍一下针对该题型的做题步骤与技巧&#xff0c;纯干货&#xff0c;认真阅读。 图:阅读理解选择题 第一种题型&#xff1a;选择题 选择题其实是在考你对于原文中提…

爬虫学习 | 02 认识爬虫spider

网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;也被称为网页蜘蛛&#xff08;Spider&#xff09;、网页机器人&#xff08;Robot&#xff09;或爬虫&#xff08;Crawler&#xff09;&#xff0c;是一种自动浏览互联网的程序。它的主要任务是按照一定的算法扫描和访问…

MySQL篇:主从复制

概述 话不多说&#xff0c;直接上概念&#xff1a; DDL&#xff08;Data Definition Language&#xff09;语句&#xff1a; 数据定义语言&#xff0c;主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。常用的语句关键字有 CREATE、DROP、ALTER 等。 DML&#xff…

【测试】总体测试计划(Word直接套用完整版)

测试目标&#xff1a;确保项目的需求分析说明书中的所有功能需求都已实现&#xff0c;且能正常运行&#xff1b;确保项目的业务流程符合用户和产品设计要求&#xff1b;确保项目的界面美观、风格一致、易学习、易操作、易理解。 软件全套文档过去进主页。 一、 前言 &#xff0…

C语言题目之打印菱形

文章目录 一、题目二、思路三、代码实现 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目 二、思路 本题目是要求打印菱形&#xff0c;对于这种打印的题目而言&#xff0c;我们能正确的写出代码&#xff0c;就得找到规律 第一步 我们先对整个菱…

【Python】基础语法(函数、列表和元组、字典、文件)

。一、函数 1、函数是什么 编程中的函数和数学中的函数有一定的相似之处。 数学上的函数&#xff0c;比如 y sin x&#xff0c;x 取不同的值&#xff0c;y 就会得到不同的结果。 编程中的函数是一段可以被重复使用的代码片段。 &#xff08;1&#xff09;求数列的和&…

【AI伦理挑战下的应对策略】构建隐私保护、算法公正与深度伪造管控机制

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《热点时事》 期待您的关注 目录 引言 一、构建可靠的AI隐私保护机制 1.1 隐私保护的重要性 1.2 数据最小化与匿名化处理 1.3 …

【轻松拿捏】Java都有哪些特性?

Java都有哪些特性&#xff1f; 1. 面向对象 2. 平台无关性 3. 简单性 4. 安全性 5. 内存管理 6. 多线程 7. 动态性 8. 分布式计算 9. 健壮性 10. 高性能 11. 丰富的标准库 12. 社区支持和生态系统 13. 可移植性 14. 安全性和强类型 15. 模块化和可扩展性 总结 …

贪心,CF 1891C - Smilo and Monsters

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1891C - Smilo and Monsters 二、解题报告 1、思路分析 操作二显然很划算的&#xff0c;但是操作2有代价&#xff0c;为了更划算&#xff0c;我们要让操作2的操作次数最少 即&#xff0c;操作二尽可能用在…

make2s:自动编译

模板Makefile&#xff0c;编译多个C/C模块成不同优化级别的平台相关的汇编码。

git查看历史记录方法

0 Preface/Foreword 1 git reflog git reflog显示所有的操作&#xff0c;不仅仅是commit&#xff0c;也包括git pull&#xff0c;checout等动作。 1.1 查看本地和远程仓库的区别 远程仓库&#xff1a;中间的提交是直接在web端编辑 远程仓库&#xff1a;最新的提交是在本地编…

超市管理系统 需求分析与设计 UML 方向

一、项目介绍 1.1项目背景 随着经济一体化和电子商务的迅速发展&#xff0c;网络传播信息的速度打破了传统信息传递的模式&#xff0c;互联网的高速发展和计算机应用在各个高校进展迅速&#xff0c;更多信息化产品的突飞猛进&#xff0c;让现代的管理模式也发生了巨大的变化&…

【Linux】04.Linux 下的软件包管理器——yum

一、常见的软件安装方式 yum安装rmp安装源码安装 其中rmp安装较麻烦&#xff0c;源码安装对用户要求较高&#xff0c;因此我们最常用的是yum安装。 二、软件生态 现实中我们如何评估一款操作系统的好坏呢&#xff0c;又如何选择一款操作系统呢&#xff1f; 我们选择操作系统…

PostgreSQL 如何应对因大量并发更新导致的锁竞争?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 如何应对因大量并发更新导致的锁竞争一、锁竞争的原因及影响&#xff08;一&#xff09;什…

国外的一组B端界面,个性化是标配,为什么?

因为国外商务合作关系非常的纯粹&#xff0c;我出钱你出力&#xff0c;你干好我买单&#xff0c;没有这么多弯弯绕。 匠心接单中...8年前端开发和UI设计接单经验&#xff0c;完工项目1000&#xff0c;持续为友友们分享有价值、有见地的干货观点&#xff0c;有业务需求的老铁&am…

[A-04] ARMv8/ARMv9-Cache的相关策略

ver0.3 前言 前面我们已经通过三篇文章反反复复的讲Cache的概念、结构、架构&#xff0c;相信大家对Cache已经大概有了初步的了解。这里简单归纳一下: (1) Cache从硬件视角看&#xff0c;是连接PE-Core和主存的一种存储介质&#xff0c;存储的数据是主存中数据的副本&#xf…

完美解决ImportError: cannot import name ‘PILLOW_VERSION‘的正确解决方法,亲测有效!!!

完美解决ImportError: cannot import name PILLOW_VERSION’的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 亲测有效 完美解决ImportError: cannot import name PILLOW_VERSION的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xf…

鸿蒙模拟器(HarmonyOS Emulator)Beta申请审核流程

文 | Promise Sun 一.背景&#xff1a; 鸿蒙项目开发需要使用模拟器进行开发测试&#xff0c;但目前想在DevEco Studio开发工具中使用模拟器就必须到华为官网进行报名申请&#xff0c;参加“鸿蒙模拟器&#xff08;HarmonyOS Emulator&#xff09;Beta活动申请”。 申请审核通…

element-ui dialog 嵌套

dialog 内部嵌套 dialog&#xff0c;内层的 dialog 层级显示会遮罩在内容的 dialog 内容区域之上&#xff0c;内层 dialog 添加 append-to-body 属性即可&#xff0c;如官方文档&#xff1a;

SpringBoot系列:通过AOP+注解优雅实现操作日志记录

文章目录 前言一、简介1.1 操作日志在企业应用中的重要性1.2 使用AOP和注解实现操作日志记录的好处 二、开发环境三、准备工作3.1 创建操作日志记录表3.2 创建系统日志实体类 四、代码实现4.1 创建业务枚举类4.2 创建日志注解4.3 创建操作状态枚举类4.4 创建IP工具类4.5 创建切…