异工同智-Java开发 二面 面经
1、详细介绍一下你最有成就感的项目
我最有成就感的项目是一个智能数据分析平台,这个平台主要为企业提供数据采集、清洗、分析和可视化的一站式解决方案。
项目背景是客户有大量的业务数据分散在不同系统中,包括ERP、CRM、财务系统等,他们希望能统一管理这些数据,并通过数据分析辅助决策。我们团队负责从零开始搭建这个平台,我在其中担任核心开发的角色。
技术架构方面,我们采用了微服务架构。后端用Spring Cloud Alibaba全家桶,包括Nacos做服务注册和配置中心,Gateway做网关,Sentinel做限流熔断,Seata做分布式事务。数据存储用MySQL做业务数据存储,MongoDB存储非结构化数据,Redis做缓存,ElasticSearch做全文检索和日志分析。消息队列用RocketMQ做异步处理和系统解耦。前端用Vue3+Element Plus。
我主要负责数据采集模块和数据分析模块的设计开发。数据采集模块支持多种数据源接入,包括数据库、API接口、文件上传等方式。我设计了一套插件化的架构,每种数据源对应一个采集器插件,通过配置就能灵活扩展新的数据源。采集到的数据先进行清洗和转换,然后存储到数据仓库。
数据分析模块是最有挑战的部分。用户可以通过拖拽的方式配置分析维度和指标,系统动态生成SQL查询。我用了模板引擎和SQL构建器来实现,支持多表关联、分组聚合、条件过滤等复杂查询。为了提升性能,我做了几个优化:1)查询结果缓存到Redis,相同查询直接返回缓存;2)大数据量查询用分页和流式处理,避免内存溢出;3)热点数据预计算,定时任务提前算好结果存起来。
项目中遇到的最大挑战是性能问题。初期版本在处理百万级数据时查询很慢,经常超时。我通过几个方面优化:1)数据库层面,给常用查询字段建索引,优化慢SQL,对大表做分区;2)应用层面,引入多级缓存,用本地缓存+Redis缓存;3)架构层面,把实时查询和离线分析分开,离线分析用定时任务预计算。经过优化,查询响应时间从10秒降到了1秒以内。
这个项目让我对系统架构设计有了更深的理解,特别是在处理大数据量、高并发场景时如何做性能优化。项目上线后得到了客户的高度认可,也为公司带来了更多的业务机会,这让我很有成就感。
2、Spring Cloud的核心组件你用过哪些,解决什么问题
我在项目中深度使用了Spring Cloud Alibaba技术栈,对各个组件比较熟悉:
- Nacos服务注册与发现,这是微服务架构的基础。每个服务启动时会向Nacos注册自己的信息,包括IP、端口、健康状态等。服务调用时从Nacos获取目标服务的实例列表,然后通过负载均衡选择一个实例调用。Nacos还支持服务分组和命名空间,可以实现环境隔离。我们用命名空间区分开发、测试、生产环境,避免互相干扰。
- Nacos配置中心,统一管理所有服务的配置。配置修改后可以动态推送到各个服务,不需要重启。我们把数据库连接、Redis地址、业务参数等都放在Nacos配置中心。还支持配置的版本管理和回滚,配置错了可以快速恢复。配置可以按环境、按服务分组管理,很灵活。
- Gateway网关,作为系统的统一入口。我们在Gateway层做了几件事:1)路由转发,根据请求路径转发到对应的服务;2)认证鉴权,验证JWT Token,判断用户权限;3)限流熔断,用Sentinel做流量控制;4)日志记录,记录每个请求的信息用于监控和排查问题;5)跨域处理,配置CORS策略;6)参数校验,拦截非法请求。
- OpenFeign声明式HTTP客户端,简化了服务间调用。只需要定义一个接口,加上@FeignClient注解,就可以像调用本地方法一样调用远程服务。Feign集成了Ribbon做负载均衡,集成了Hystrix做熔断降级。我们还配置了请求重试、超时时间、日志级别等参数。
- Sentinel流量控制,这是阿里开源的流量治理组件。我们用它做了几个方面的控制:1)QPS限流,限制接口每秒请求数;2)线程数限流,限制并发线程数;3)熔断降级,接口异常率或响应时间超过阈值时自动熔断;4)热点参数限流,针对特定参数值限流;5)系统自适应限流,根据系统负载自动调整限流阈值。Sentinel有可视化的控制台,可以实时查看流量情况和调整规则。
- Seata分布式事务,解决跨服务的事务一致性问题。我们用的是AT模式,对业务代码无侵入,只需要加@GlobalTransactional注解。Seata会自动生成回滚SQL,事务失败时自动回滚。我们在订单创建、库存扣减、积分增加这种跨服务场景用Seata保证数据一致性。
- Sleuth链路追踪,给每个请求生成唯一的traceId,可以追踪请求在各个服务间的调用链路。配合Zipkin可以可视化展示调用链,快速定位性能瓶颈和异常点。我们在排查线上问题时经常用链路追踪,很方便。
这些组件组合起来,解决了微服务架构中的服务治理、配置管理、流量控制、分布式事务、链路追踪等核心问题,让我们可以专注于业务开发。
3、如何保证系统的高可用性
系统高可用是我们架构设计的重点,主要从这几个方面保证:
- 服务冗余和负载均衡,每个服务至少部署3个实例,分布在不同的服务器上。前面用Nginx做负载均衡,配置健康检查,实例异常自动摘除。服务内部用Ribbon或LoadBalancer做客户端负载均衡,支持轮询、随机、权重等策略。这样单个实例挂掉不影响整体服务。
- 数据库高可用,MySQL配置主从复制,一主两从架构。主库负责写操作,从库负责读操作,实现读写分离。主库宕机后,通过MHA或Orchestrator自动切换到从库。我们还配置了双主模式作为备份方案。数据库连接池用Druid,配置了连接检测和自动重连。
- 缓存高可用,Redis用哨兵模式,一主两从三哨兵。主节点宕机后哨兵自动选举新的主节点,实现故障自动转移。我们还在应用层做了降级处理,Redis不可用时降级到数据库查询,虽然慢一点但保证服务可用。
- 消息队列高可用,RocketMQ配置主从同步,消息写入主节点后同步到从节点才返回成功。NameServer部署多个节点,Broker注册到所有NameServer。这样单个节点故障不影响消息收发。
- 限流熔断降级,用Sentinel做流量控制。配置了QPS限流、慢调用熔断、异常比例熔断等规则。接口异常时快速失败,返回降级数据或友好提示,避免雪崩效应。非核心功能可以降级,比如推荐服务挂了就返回默认推荐。
- 超时和重试机制,所有的远程调用都配置了超时时间,避免无限等待。对于幂等的接口配置了重试机制,失败后自动重试3次。用指数退避算法,重试间隔逐渐增加,避免雪崩。
- 异地多活,核心服务部署在两个机房,通过专线同步数据。一个机房故障时流量自动切换到另一个机房。我们用DNS做流量调度,配置了健康检查和自动切换。
- 监控告警,用Prometheus采集系统指标,Grafana做可视化展示。配置了多维度的告警规则,包括服务可用性、接口响应时间、错误率、系统资源等。告警通过钉钉和短信通知,确保第一时间发现问题。
- 容灾演练,定期做故障演练,比如模拟数据库宕机、服务宕机、机房断网等场景。验证系统的容错能力和应急预案。每次演练后总结问题,持续改进。
- 灰度发布,新版本先发布到一小部分实例,观察没问题再全量发布。用Gateway做流量控制,可以按比例或按用户分流。发现问题可以快速回滚。
通过这些措施,我们系统的可用性达到了99.95%以上,基本满足了业务需求。
4、JVM内存溢出如何排查和解决
JVM内存溢出是生产环境常见的问题,我有一些排查和解决的经验:
- 问题现象,通常表现为应用突然无响应,日志中出现OutOfMemoryError异常。可能是堆内存溢出、栈溢出、元空间溢出等不同类型。首先要看异常信息确定是哪种类型的OOM。
- 堆内存溢出排查,这是最常见的情况。首先配置JVM参数-XX:+HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath,OOM时自动dump堆内存。然后用MAT或JProfiler分析dump文件,看哪些对象占用内存最多。常见原因有:1)内存泄漏,对象无法被GC回收,比如集合类持续增长没有清理、ThreadLocal没有remove、静态集合持有大量对象;2)内存溢出,对象太多超过堆容量,比如一次性加载大量数据、
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经,带你练透java圣经
