Java开发常见问题分析和处理方案
程序Bug的产生,通常分为三种类型
逻辑漏洞:
低级错误,程序执行后无法达到想要效果。越界访问:
访问了非法区域,造成程序崩溃。条件考虑不全面:
你以为你万无一失,但你永远都不知道输入参数究竟是什么!
如何防范未知Bug:异常捕获
异常捕获一般依靠try,catch语句。很好理解:try(尝试)一下,如果有问题,直接捕获 (catch)住,防止程序崩溃。
如果核心流程处理到一半服务器崩了怎么处理?
这里同时存在三个问题:
- 问题排查以及快速恢复
- 异常数据修复
- 服务高可用,规避服务宕机
1、先抢通业务
当发现服务器宕机后,最关键的是抢通业务,而不是抢修服务器。
因此,需要做应急方案。最好准备2个网站服务器,他们存放的内容相同,而ip不同,并且机房的地理位置不同。这样第一时间发现宕机问题后,可以迅速的通过修域名记录,指向目前正常的网站空间。而且2个主机,同时宕机的可能性就大大降低了。
2、定位服务器崩溃原因
- 内存溢出,磁盘资源耗尽
- 线程死锁,进程过多或者不断创建,耗尽资源导致
- 数据库慢查询,连接数过多,临时表不够用,程序死锁
- 主备数据不一致
- 应用程序异常
- 流量负载过大
- DOSS攻击
- 散热问题
3、异常数据修复
- 写数据做事务控制,保障数据安全。
- 磁盘备份,重启服务时恢复数据。
- 记录关键日志。
4、服务高可用
- 服务多实例集群部署,负载均衡策略访问,做好服务降级、服务限流。
- 数据库读写分离、分库分表方案。
- 做好服务性能测试、压力测试。
开发中常见问题
空指针异常
在访问或操作对象之前,检查对象是否为null
类型转换异常
在进行类型转换之前,先检查对象的类型是否与目标类型兼容。
金额数值计算精度问题
金额一般都是用BigDecimal
循环条件错误
可能会导致死循环或者无法执行
文件操作异常
文件操作之前,先检查文件是否存在、是否可读写等。
事务不起作用没有回滚
异常被try.catch吃了,手动抛了别的异常Exception,默认情况下只会回滚RuntimeException
访问权限不是public;方法用final,static修饰;方法内部调用;
未开启事务;未被spring管理,需要创建bean实例。
内存溢出异常
在编写程序时,要注意控制内存的使用,及时释放不需要的对象。
性能问题
比如使用缓存、减少对象创建、优化算法等。
大数据量导出Excel存在问题及优化方案
问题1:一次性获取全部数据到内存当中,容易引起系统OOM。
解决方案:分页查询数据,分批处理。
问题2:分页查询存在深度分页问题,数据偏移量越大导致sqL查询变慢。
解决方案:使用标签记录优化(id自增且连续)、索引覆盖优化。
问题3:查询数据串行耗时长。
解决方案:可以通过线程编排,并行执行sql查询,最后顺序导出到excel。
问题4:一个excel文件数据过大,用户存在打不开的情况。
解决方案:通过easyexcel多sheet页导出数据。
如何保证接口幂等性?
概念:同一个接口,多次发出同一个请求,必须保证操作只执行一次。
什么情况下,会产生接口幂等性的问题?
- 网络波动, 可能会引起重复请求
- 用户重复操作,用户在操作时候可能会无意触发多次下单交易,甚至没有响应而有意触发多次交易应用
- 使用了失效或超时重试机制(Nginx重试、RPC重试或业务层重试等)
- 页面重复刷新
- 使用浏览器后退按钮重复之前的操作,导致重复提交表单
- 使用浏览器历史记录重复提交表单
- 浏览器重复的HTTP请求
- 定时任务重复执行
- 用户双击提交按钮
如何保证接口幂等性?
- 业务字段加唯一约束(简单)
- 令牌+唯一约束(简单推荐)客户端每次在调用接口的时候,需要在请求头中,传递令牌参数(令牌可以存储到redis中),每次令牌只能用一次。一旦使用之后,就会被删除,这样可以有效防止重复提交。
- mysql的insert ignore或者on duplicate key update(简单)
- 共享锁+普通索引(简单)
- 利用MQ或者Redis扩展(排队)
- 同步锁(单线程,集群可能会失效)
- 分布式锁如redis(实现复杂)
- 其他方案如多版本控制MVCC 乐观锁 悲观锁 状态机等。。。
实际开发中,如何正确使用多线程?
- 处理并行任务:多线程可以同时处理多个任务,提高程序的执行效率。比如批量处理数据、同时上传多个文件等。
- 事件驱动的编程:Java多线程可以用于事件驱动的编程,如GUI、网络编程等。
- 并发访问共享资源:多线程可以应用于并发访问共享资源的场景,如数据库连接池。
- 高效的IO操作:在网络编程中,Java多线程可以提供高效的IO操作,如同时读写多个Socket。
- 多任务协同处理:在复杂的任务中,不同的任务可以以各自独立的方式并行运行,最终合并结果。
- 节约资源:多线程可以提高CPU和内存的使用效率,使得我们能够更好地利用系统资源。
- 提高用户体验:在一些高并发场景下,如网站、游戏等,使用多线程可以提高用户体验,使得用户能够更快地得到反馈。
- 线程安全问题:
多个线程同时访问共享资源时可能导致数据不一致或异常。解决方案包括使用同步机制(如synchronized关键字、Lock对象)、使用线程安全的数据结构、避免共享状态等。 - 死锁问题:
多个线程因相互等待对方释放资源而无法继续执行。解决方案包括避免循环等待资源、按照固定顺序获取资源、设置超时时间等。 - 上下文切换问题:
线程切换需要耗费一定的时间和资源,如果线程频繁切换,会降低程序性能。解决方案包括合理设计线程数量、减少线程间的竞争、使用线程池等。 - 数据同步问题:
多个线程访问共享数据时,可能出现数据不一致的问题。解决方案包括使用锁来保证数据的原子性、使用volatile关键字保证可见性、使用线程安全的数据结构等。 - 过度创建线程问题:
创建线程需要消耗系统资源,如果过度创建线程,可能导致系统资源耗尽。解决方案包括使用线程池来复用线程、合理设置线程池大小等。
定时任务如果集群,如何保证不被重复执行?
- 独立部署,将定时任务独立出来,成为一个单独的项目工程,单一部署
- 配置实现,配置文件设置一个标识符号,定时任务读取此配置文件此属性, 读取到ture执行定时任务,否则不执行
- 利用分布式锁,虽然两个机器都会运行定时任务,但是一个时刻只有一台机器会真正的执行定时任务的核心方法
一个订单30分钟未支付自动取消功能,有几种实现方案?
- 数据库轮询
该方案通常是在小型项目中使用,即通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行 update 或 delete 等操作。优点:简单易行,支持集群操作。
缺点:对服务器内存消耗大;
存在延迟,比如你每隔 3 分钟扫描一次,那最坏的延迟时间就是 3 分钟;
假设你的订单有几千万条,每隔几分钟这样扫描一次,数据库损耗极大。 - JDK 的延迟队列
该方案是利用 JDK 自带的 DelayQueue 来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入 DelayQueue 中的对象,是必须实现 Delayed 接口的。优点:效率高,任务触发时间延迟低。
缺点:服务器重启后,数据全部消失,怕宕机;集群扩展相当麻烦;代码复杂度较高;
因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常。 - 时间轮算法
时间轮算法可以类比于时钟,按某一个方向按固定频率轮动,每一次跳动称为一个 tick。优点:效率高,任务触发时间延迟时间比 delayQueue 低,代码复杂度比 delayQueue 低。
缺点:服务器重启后,数据全部消失,怕宕机;集群扩展相当麻烦;
因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常。 - Redis 缓存
思路一:利用 Redis 的 zset,zset 是一个有序集合,每一个元素 (member) 都关联了一个 score, 通过 score 排序来取集合中的值。
思路二:使用 Redis 的 Keyspace Notifications,中文翻译就是键空间机制,就是利用该机制可以在 key 失效之后,提供一个回调,实际上是 Redis 会给客户端发送一个消息。是需要 Redis 版本 2.8 以上。优点:由于使用 Redis 作为消息通道,消息都存储在 Redis 中。如果发送程序或者任务处理程序挂了,重启之后,还有重新处理数据的可能性;做集群扩展相当方便;时间准确度高。
缺点:需要额外进行 Redis 维护。 - 使用消息队列
可以采用 RabbitMQ 的延时队列。RabbitMQ可以实现延迟队列。优点:高效,可以利用 RabbitMQ 的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。
缺点:本身的易用度要依赖于 RabbitMQ 的运维。因为要引用 RabbitMQ, 所以复杂度和成本变高。
为什么不用eureka非要用nacos作为注册中心?
nacos在自动或手动下线服务,使用消息机制通知客户端,服务实例的修改很快响应;Eureka只能通过任务定时剔除无效的服务。
nacos可以根据namespace命名空间,DataId,Group分组,来区分不同环境(dev,test,prod),不同项目的配置。
Mq如何保证消息不丢失?
丢数据一般分为两种,一种是mq把消息丢了,一种就是消费时将消息丢了。
Mq如何保证消息顺序的一致性?
如何避免消息一直堆积在mq服务器端?
在遇到消息堆积的时候,先检查下导致堆积的原因,可能有如下几种:
- 消费失败时大量重试导致消息堆积。
- 消费者程序的故障:如 程序死锁,io阻塞等。
- 消费者资源瓶颈:目前的主流消息队列,单个节点消息收发的性能可以达到万级别甚至10万级+的水平。除非容量预估没有做好,一般不会出现这种问题。即使出现这种问题,通过Scale Out Broker 的实例数也是比较轻松可以解决的。
消息堆积的解决方案:
- 提高消费者数量;更多的消费者将允许同时处理更多的消息,并减少消息堆积。
- 调整超时设置;例如,在某些情况下,因为某些原因(例如网络延迟),MQ 消费者需要等待更长时间才能接收到新的消息。
- 批量操作;例如,在生产者端,您可以使用管道来一次性发送多条信息。在消费者端,您可以使用批处理来一次性处理多个消息。
- 数据结构优化;例如,在使用MQ时,可以通过在消息中添加一些元信息来优化处理流程,或者采用更合适的数据结构存储消息,以减少在 MQ 中积累的消息数量。
Mq异步消费,如何获取到返回结果?
以下用Rabbit为例:
- 异步操作,获取回调消费结果,需要实现RabbitTemplate.ConfirmCallback 接口,然后重写 confirm()方法。
- 获取回调结果,指的是获取消息是否被消费端正常消费而返回的结果,并不是消费端返回的处理结果,这一点得注意,如果需要等待消费端返回处理结果,则需要做同步操作,而不是做回调操作。
- 需要做同步操作时,应该rabbitTemplate.convertSendAndReceive()方法,返回结果类型是Object,需要根据消费端返回的数据类型来决定强转的类型。
- 异步则使用rabbitTemplate.convertAndSend()方法。
常见业务功能实现技术选型
需求描述 | 技术选型 |
---|---|
Excel、Word、Pdf文件操作 | Apache POI,Spire,Asponse,EasyExcel,Stirling-PDF |
在线文档编辑预览技术 | OnlyOffice,OpenOffice |
图片处理 | Thumbnailator |
分库分表中间件 | ShardingSphere,Mycat,DBLE |
任务调度 | XXL-Job,Quartz,Elastic-Job,TBSchedule,Saturn |
大数据同步 | Datax,Otter,Canal |
消息推送 | WebSocket,Server-Sent Events |
表达式引擎 | JEXL,Aviator,jfireEL |
模板引擎 | Thymeleaf,Freemarker,Velocity,Beetl,Enjoy,JSP |
前端框架 | Vue,Angularjs,React,Bootstrap,LayUI,EasyUI,Jquery |
报表开发 | iReport,EasyReport,JimuReport,SpringReport,JFreeChart,ECharts |
OA工作流审批 | Activiti,Flowable,Jbpm,Osworkflow |
MQ消息队列 | ActiveMQ,RabbitMQ,RocketMQ,kafka |
代码生成器 | mybatis-plus-generator,EasyCode |
接口文档 | Knife4j,Swagger,Apifox,YApi,JApiDocs |
数据库表结构文档生成工具 | screw(螺丝钉),database-export |
热门开发工具包 | Hutool |
Java开发常见问题分析和处理方案的更多相关文章
- 微信小程序开发常见问题分析
距离微信小程序内测版发布已经有十几天的时间了,网上对微信小程序的讨论也异常火爆,从发布到现在微信小程序一直占领着各种技术论坛的头条,当然各种平台也对微信小程序有新闻报道,毕竟腾讯在国内影响力还是很大的 ...
- Web开发常规调试方法与常见问题分析
一.Web项目基本原理 现在的web项目大都已经前后端独立开发与部署. 前后端独立开发,一般是前端与后端通过web接口(常见的有RESTful与websocket)文档进行交流.前端开发人员先更具业务 ...
- 《阿里巴巴Java开发手册》扫描插件正式发布--插件安装和使用分析
"不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!" 阿里巴巴于10月14日上午9:00在杭州云栖大会<研发效能峰会>上,正式发布<阿里巴巴Java开发 ...
- 2019最新最全Java开发面试常见问题答案总结
2019最新最全Java开发面试常见问题答案总结 马上准备9月份出去面试Java开发,自己学习丢西瓜捡芝麻,学了的都忘了,所以有机会自己做个学习笔记,摘录自各个博文以及总结. 1.JAVA面向对象的特 ...
- Java开发网络安全常见问题
Java开发网络安全常见问题 等闲识得东风面,万紫千红总是春 1.敏感信息明文传输 用户敏感信息如手机号.银行卡号.验证码等涉及个人隐私的敏感信息不通过任何加密直接明文传输. 如下图中小红书APP 的 ...
- 如何透彻分析Java开发人员
第一部分:对于参加工作一年以内的同学.恭喜你,这个时候,你已经拥有了一份Java的工作. 这个阶段是你成长极快的阶段,而且你可能会经常加班.但是加班不代表你就可以松懈了,永远记得我说的那句话,从你入行 ...
- Linux(Ubuntu 16) 下Java开发环境的配置(二)------Tomcat的配置及常见问题
前言 相比于java JDK的配置,Tomcat的配置简单的多,简直就相当于直接运行了,本文以Tomcat8.0为例进行配置 1.Tomcat的下载 地址:https://tomcat.apach ...
- JAVA开发相关
JAVA开发相关1. IntelliJ IDEA开发工具熟练使用2. Maven3. Spring框架(IoC.AOP) 1)数据库相关MyBatis 2)数据库连接池 3)事务.多数据源.跨数据库分 ...
- 常用 Java 静态代码分析工具的分析与比较
常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...
- java开发常用jar包介绍(转载)
jta.jar 标准JTA API必要 commons-collections.jar 集合类 必要 antlr.jar ANother Tool for Language Recognition ...
随机推荐
- csapp-attacklab(完美解决版)
注意:必须阅读Writeup,否则根本看不懂这个lab要怎么做 实验前准备 1.在终端中输入./ctarget和./rtarget结果报错 百度后得知自学的同学需要在执行文件时加上-q参数,不发送结果 ...
- jeecg-boot中分页接口用自定义sql和list实现
1.controller中 @ApiOperation(value="分析仪工作状态和报警-3列-分页", notes="分析仪工作状态和报警状态-分页") @ ...
- 远程控制软件 TeamViewer 的局限性和替代方案
TeamViewer 公司创建于2005年,总部位于德国,客户遍及全球,其中企业用户居多,其各方面性能都很不错,但价格却非常贵.针对个人用户,TeamViewer 提供免费版软件,但时不时会提示&qu ...
- Ubuntu 启用交换分区
前言 交换分区也称之为 swap 分区,允许系统在内存不足的情况下将内存程序写入文件,防止系统卡死失去响应的情况发生. 检查现有交换分区 首先,确认系统中是否已存在交换分区或文件.在终端中输入以下命令 ...
- hadoop部署2
完全分布式部署介绍 学习目标 完全分部式是真正利用多台Linux主机来进行部署Hadoop,对Linux机器集群进行规划,使得Hadoop各个模块分别 部署在不同的多台机器上. 能够了解完全分布式部署 ...
- salesforce零基础学习(一百三十七)零碎知识点小总结(九)
本篇参考: https://help.salesforce.com/s/articleView?id=release-notes.rn_lab_conditional_visibiliy_tab.ht ...
- P1036 [NOIP2002 普及组] 选数
传送锚点:https://www.luogu.com.cn/problem/P1036 题目描述 已知 \(n\) 个整数 \(x_1,x_2,\cdots,x_n\),以及 \(1\) 个整数 \( ...
- 一文搞懂C++继承、多继承、菱形继承、虚继承
继承 目录 继承 继承 继承的访问权限 子类赋值给父类 赋值兼容规则 "天然"的行为 验证: 1. 其他权限继承能否支持赋值兼容规则 2.是否"天然",有没有产 ...
- 分享5款.NET开源免费的Redis客户端组件库
前言 今天大姚给大家分享5款.NET开源.免费的Redis客户端组件库,希望可以帮助到有需要的同学. StackExchange.Redis StackExchange.Redis是一个基于.NET的 ...
- SwiftUI Stack中的View被压缩的效果
一.背景 我们在布局中,经常会遇到视图元素排列时空间不足或者空间过大的情况,在这种场景下面,不同的布局方式有不同的方法: 绝对布局frame:纯靠计算过程控制,获取父视图的大小,根据需求,计算自己需要 ...