第一部分 Java基础
第二部分 Java进阶

Java p2p项目面试题

P2P项目专题

● 具体的你在P2P项目中都干什么了,你负责哪一块,每一块实现的时候用到了哪些技术?

● 你们项目的并发量设计了多少?

● P2P项目上线了吗?

● 你项目中的事务是怎么处理的?

● 在秒杀项目中使用消息队列ActiveMQ进行流量削峰,如果ActiveMQ接收消息失败了,怎么办?

消息在接收后会被服务器删除,为了避免接收消息失败而消息又被服务器删除,此时我们可以关闭自动确认机制AUTO_ACKNOWLEDGE,采用手动消息确认机制,由程序进行消息的确认,接收消息发生异常,则不确认消息,以便于下次可以再次接收。

● 在秒杀项目中使用消息队列ActiveMQ进行流量削峰,如果ActiveMQ挂掉怎么办?

第一点,首先消息需要使用持久化消息,服务挂掉,重启服务后消息依然可以消费,不会丢失;

第二点,ActiveMQ采用主从模式搭建集群,比如搭建3台主从模式的ActiveMQ集群,提高服务的可用性;

● 在交易中,如何控制超卖问题(卖出去的商品大于数据库实际商品库存)?

解决超卖问题,一个是借助于锁机制实现,这里面有线程锁、数据库锁、分布式锁等,另一个是借助于某些中间件产品实现,比如Redis;

如果我们的服务只是部署了一台服务器,我们通过线程锁即可控制并发问题,控制了并发问题,也就不会产生减库存的冲突,即不会产生超卖问题,这种实现,效率不高,而且只能是单机部署,实际项目不会采用;

如果我们的服务是集群部署,线程锁就不行了,此时可以使用数据库锁或分布式锁控制并发问题,从而控制减库存的冲突,避免超卖问题,数据库锁可以采用乐观锁、悲观锁,其中乐观锁比悲观锁效率稍高,在实际项目中使用多一些,悲观锁使用较少,但由于数据库本身的性能和并发处理能力并不理想,在高并发项目中,使用数据库锁也是不合适的;

使用分布式锁解决超卖问题,在实际项目中有相关真实的案例,主要采用zookeeper实现分布式锁,分布式锁是将我们的线程锁扩展为多个jvm的锁,代码在多个jvm上执行时,分布式锁也能进行锁定,因为能锁定就能控制并发,控制了并发即能控制减库存的冲突,即可解决超卖问题;

使用一些中间件产品解决超卖问题被经常使用,最被常用的是Redis,在实际项目中被大量使用,由于Redis是单线程的,不管有多少个并发请求,Redis会将请求排队进行处理,即一个一个地有先后顺序地处理,这样即不会有并发问题,即不会产生减库存的冲突,从而解决减库存的超卖问题;

● 在实际项目中,是否使用过多线程?

在P2P项目中,比如在用户投资到期后需要给用户回款,此处我们使用了多线程,加快整个回款的速度,我们先从数据库获取所有待回款的数据,然后创建一个线程池,每个回款是一个线程,将这些回款线程提交到线程池中执行,从而充分利用服务器的CPU资源快速为用户回款;

再比如当每个投资用户生日时,我们会在用户生日当天给用户送一个生日红包,由于同一天有大量用户生日,我们也是通过多线程为用户送红包,先从数据库获取当天生日的用户,然后创建一个线程池,给每个用户发红包是一个线程,将这些发红包线程提交到线程池中执行,从而加速生日红包的发送任务;

● P2P中的投资及收益金额采用Java中的什么数据类型进行存储?

由于涉及到精度问题,我们项目中都采用BigDecimal类型,以避免在计算收益时,导致金额精确的损失。

● 你们这个P2P项目上线后采用的是什么访问协议?

为了数据传输的安全性,我们的p2p项目访问的时候,全部都https协议,https协议会将数据加密传输,提高安全性,我们当时公司的运维部门采购了https的安全证书,在服务器上搭建了https协议的访问方式,如果用户采用http访问,我们会自动跳转到https协议打开网页;

● 你们P2P项目对金钱是怎么处理的?

项目中涉及到的资金问题,有几处处理,一个是我们有一个后台对账系统,每天会根据第三方支付系统的结算清单,与我们这边的充值数据进行对账,保证我们与第三方的数据一致;

对于用户投资到期后,提现自己的本金和收益,我们后台系统有专门的提现审核功能,通过系统审核该投资用户的资金流是否有异常,无异常方可通过提现审核。

● 你们使用定时任务是干什么的?

我们使用定时任务主要是处理一些定时或延迟的工作,这些工作不需要马上处理,就配置好时间,让程序在指定的时间或者指定的频率去执行,比如我们在理财产品投资满标后,会生成收益计划,投资到期后给用户返回收益等,我们都是采用定时任务来完成的,Spring框架集成支持定时任务,我们采用的就是spring框架下的spring-task来实现定时任务;

● 请你描述一下整个P2P的支付流程?

支付模块,我们当时对接了两家,一家快钱支付,一家丰付支付,当时是由我开发的,我们的商务和对方谈好后并签订了支付协议,对方的技术给我们提供了相关的支付接口文档及demo,我主要是根据对方的接口文档进行开发,首先是调用对方提供的支付下单接口,把我这边准备好的参数传给对方,然后调用对方接口,根据对方的返回信息进行处理,如果对方返回成功,然后调用对方的获取短信验证码接口,此时将给用户的手机号发送一个支付验证码,用户输入支付短信验证码后,点击确定支付,然后我们提交支付请求,对方将返回支付的结果,支付结果对方会通过两种方式返回,一个是同步返回,一个是异步返回,我们接收对方的这两个返回结果,更新我们的数据库状态,完成整个支付流程;

● 请介绍一下这个P2P项目的整体架构及你做了什么?

整个P2P项目第一个版本,我们是采用普通的ssm框架进行开发的,是一种集中式的开发方式,上线一年之后,随着公司发展和业务需要,我们原来的ssm架构的项目,代码非常庞大和混乱,一个方法可能出现好几百行,里面很多逻辑,要新增一个功能,开发特别慢,由于修改这个功能,可能又导致另一个功能出现问题或者bug,后来我们对整个p2p项目进行了重构,采用分布式开发方式,当时选择了非常流行的Dubbo分布式开发框架,主要架构是spring mvc + spring + dubbo +mybatis的架构,另外还有一些中间件,dubbo注册中心zookeeper,缓存Redis、队列ActiveMQ、文件存储FastDFS,Session同步Sprign Session等;

在这个项目中,我参与了整个过程的开发,当时公司处于快速发展中,工作分工并不明确,前后台基本都会参与开发,我先是开发了p2p前端网站部分的理财产品展示、用户投资、用户充值三大功能模块,同时开发这些模块对应的Dubbo服务,其中的支付模块,是单独一个项目,主要对接第三方支付接口,快钱和丰付,这个项目全部是我完成的,对此我也比较熟悉。

● 你们这个P2P项目的并发量大概多少,部署了几台tomcat?

我们P2P项目有三端,一个是PC端,一个是H5端,一个的App端,其中H5端的流量比较小,并发量也很低,PC端和App端并发量高一些,其中App端并发量最大,因为App端的用户最多,App端的后端接口部署了5台tomcat,最大的并发是3500左右,这个3500是同时处理请求的能力,而不是一段时间或者多少秒的处理能力,QPS大约是30万左右,整个平台大约有200万左右的用户;

● 你们P2P项目中分布式事务怎么解决和处理的?

我们这个P2P项目,后端的服务,没有再拆分,就是一个dubbo服务,所以一个事务请求会提交到一个项目单元上执行,这样我们是避免了分布式事务的问题,因为对于一般的中小型项目,也建议不涉及到分布式事务的问题,也就是说能避免尽量避免,而在一些大型项目中无法避免需要分布式事务时,目前常用的解决方案是:

1、两阶段提交;

2、三阶段提交;

3、TCC补偿;

4、异步确保;

5、最大努力通知;

● 为什么充值会发生掉单问题?怎么解决的?

充值时候与第三方接口对接的过程中,涉及到多个系统,每个系统都无法保证整个充值过程中都是100%的高可用,还有网络等原因,就不可避免会出现某个系统成功了,另一个系统没有成功的问题,当出现这种情况的时候,这笔充值就会出现数据状态的不一致,也就是掉单,为了解决该问题,我们采用的是一种补偿机制,在发生掉单后,进行自动补偿,系统开启一个定时任务,对出现掉单的订单进行再次补偿,我们会先检索出掉单的订单,然后通过第三方支付系统的接口,查询该订单的充值状态,如果第三方已经成功了,我们这边系统就需要更新相关的数据;

● 你们的P2P项目使用Redis主要做什么?

在该项目中,最初没有使用Redis,是边运营边迭代升级的,在没有使用Redis的时候,我们的前端业务系统上的所有数据都是直接到达数据库获取,导致我们后端的数据库经常出现cpu及io压力很大,后续我们将前端业务系统上一些不需要实时更新的数据,一些频繁查询的热点数据,进行了Redis缓存存储,来提升系统的能力。

● 生产环境(线上环境)中出现的问题,你们是怎么解决的?

生产中的问题,发现后由该系统的技术负责人全力协调解决,如果是紧急影响较大的bug,会暂时下线该功能,快速对该问题进行修复,然后由测试团队进行严格测试,再上线,再次上线前将之前由于bug产生的数据问题进行修复。处理线上问题的步骤是先判断问题的严重程序、波及范围等,优先快速恢复服务,让用户可以继续使用,然后再解决bug,排查bug主要是根据线上日志、数据库数据等;

● 你们P2P项目的利息是怎么计算的?

利息的计算,公司的产品经理提供了计算公式,我们技术人员根据计算公式进行计算,由于涉及到精度问题,所有计算都是采用BigDecimal类型进行加减乘除;

● 用户在你的P2P充值,如何防止你的请求被黑客拦截,给你返回一个假的充值成功结果?实际用户未支付,但你系统给用户充了值?

这个问题,我们有签名验签机制就保证了,我们的请求中都有一个签名串,签名串黑客无法伪造,如果签名串验证无法通过,我们将不会给用户充值,提示签名失败;

● 如何防止用户重复点击、重复提交充值?

用户点击后我们会将用户的提交在redis中存放一个标志,如果用户重复提交,我们会检查redis的标志,来拒绝用户的第二次提交,值处理第一次提交请求;

● 用户的钱的整个流转过程是怎么样的?

用户通过第三方充值渠道,将用户银行卡的资金划入到P2P平台在第三方支付公司开通的账户中,然后我们会把用户的充值金额记录在我们的数据库用户资金记录表中,当用户投资某个产品,比如100元,我们会将用户资金记录表中的资金冻结掉投资金额100元,当投资到期后,会产生收益,比如收益是1元,那么我们就会将之前冻结的100元,再加上收益1元返回到用户的资金记录表中,最后用户提现101元,我们的后台结算系统审核用户的提现金额,审核通过后,通过第三方支付公司,从我们P2P平台在第三支付公司开通的账户中扣除101元,将101元打入用户提交的银行账号中;

● 请介绍一下你做的这个P2P项目?

该项目是一个基于互联网金融的网贷平台,有理财端和借款端,我主要是参与做的理财端,该项目主要包括PC站、M站、APP客户端(Android、iOS),由多个项目系统构成,包括前端业务系统PC端和H5端、数据接口系统、核心系统、结算系统、支付系统、定时任务系统、营销活动系统,红包系统,合同签章系统、实名认证接口系统、轮播图系统等。

整个项目采用分布式开发模式,Tomcat集群部署,采用Nginx实现负载均衡和动静分离,MySQL主从复制模式,Redis集群模式,ActiveMQ的异步处理、Zookeeper做为注册中心,Spring session共享,Redis集群缓存热点数据提升系统吞吐量,整个项目采用的技术架构主要是:Spring mvc + Spring + Dubbo +MyBatis, 采用Dubbo实现项目间的RPC调用,采用分布式文件系统FastDFS存储投资借款合同。

我在这个平台中参与过前端业务系统,Dubbo数据接口系统,支付接口系统、合同签章系统的开发,对这几个系统比较熟悉,通过这个项目,遇到过一些问题,也学到很多东西。比如最早的时候,对Dubbo开发框架不是很了解,通过该项目,现在比较得心应手。

互联网分布式专题

● 你都知道哪些技术可以完成异构系统整合?

httpclient、webservices

HR专题

● 自我介绍?

面试官您好,我叫XX,非常高兴认识您。到目前为止我从事Java软件编码工作已经3年了,之前一直在石家庄的XX公司工作,他是一家外包公司,在这期间我接触了有六七个项目,其中包括政府部门的项目、银行相关的项目、还有互联网公司相关的项目,最近做的是一个P2P互联网金融项目。北京这边毕竟软件环境好一些,有一些朋友也来到北京发展情况挺好的,所以前两天把石家庄的工作辞掉了,想在北京闯一闯。这就是我的个人情况,谢谢。

说明:这只是一个参考的模板,自行修改,并且在进行自我介绍的时候不要死记硬背。要用描述性的语言说出来。

● 说一个我们留下你的理由?

首先,我个人非常喜欢热爱Java软件开发这份工作,我喜欢耐心的做一件事,实现一个一个客户的需求。

其次,我的技术能力完全可以胜任咱们这份工作,技术这块您放心,肯定不掉链子,按时按点完成领导交办的任务。

另外,我也喜欢咱们公司的企业文化以及工作氛围。希望贵公司能给一次机会。

● 你还有什么要问的吗?

基本上也没什么问题了,我就是想知道一下咱们团队开发使用的是哪些技术,如果可以的话,我回去抓紧时间熟悉一下。比如用的哪些框架,后台使用的什么技术,前端使用的什么框架等。

● 你的期望薪资是多少?

多种回答方式:第一种是直接说一个薪资值,例如:10K左右是可以接受的(带个左右,不要说区间值,千万别说10~15)。第二种方式可以这样说:我来之前也对北京这块的薪资结构有了一定的了解,3年工作经验在北京这块大概在12K以上,所以12K左右都可以接受,当然,薪资这块不是硬性要求,能够遇到一个好的团队,优秀的企业这是最主要的。

● 说一下职业规划?

其实具体的职业规划目前也没有刻意的去制定过,目前来说我还是希望能够把技术底层再好好的研究一下,比如像数据结构、算法、框架底层源代码等。我还是比较喜欢钻研技术。

● 你平时除了开发还干什么?

平时除了编码之外,主要还是为公司产品解决一些线上的问题,调一些bug。另外还会写日报周报、参与各种会议、和产品沟通、和测试沟通等等,闲暇时间会学习一些新的技术。

● 项目经理通过什么方式分配任务?

这个问题的答案不是固定的,因为每个团队的管理方式不同。比较正规的大的公司一般会使用专业的工具,例如project、Planisware工具,但这些工具使用复杂。对于一些规模比较小的公司来说一般excel就搞定了,在excel表格中描述任务并自动生成甘特图来跟踪任务的进展。(建议这样回答:我们项目组使用的excel进行任务分配的,在excel中标上一些特殊的颜色,来表示不同的进度。)

● 项目经理怎么监控项目进度的?

每一天我们都要按时提交日报,每一周都要按时提交周报,项目经理通过日报周报等形式监控项目进度。

● 项目经理怎么监控代码质量的?

不定期的进行代码走查(代码review),项目经理、组长、程序员一起到会议室,打开投影仪,把最近几天的代码一行一行的看一看,主要看看代码的注释、代码的格式、代码的命名规范、代码的冗余度等。

● 怎么和测试沟通的?

● 你平时和谁沟通较多?

通过上图可以看出,开发通常和产品、测试沟通较多。

● 你们小组是怎么沟通的?

● 你们平时都什么时候开会,都开什么会?

一般都会有晨会(小组会议)。

每日晨会是敏捷开发过程中最为重要的一个环节。核心团队成员每天早上开一个非常短的碰头会,每人平均2到3分钟,介绍昨天做了什么,今天要做什么,有什么困难没有。 

主要目的是便于项目管理人员了解任务开发状态,发现潜在的隐患,督促团队成员勤勉工作,帮助解决困难。

一般采用站立式非正规会议,集中在一个小会议室或者是在稍微偏僻一点的走廊。 

当项目管理人员发现某个团队成员工作不力或者是遇到困难的时候,除在会议上作简短确认以及询问其它团队成员能否帮助外,还应在会后与当事人进行详细沟通。

有一些公司会有夕会,下班时候的一个碰头会(小组会议)。

每周都会有周例会(公司的所有成员会议)。

● 为什么从上家公司离职?

北京这边的软件环境好一些,趁年轻想来大城市闯一闯。

● 你上家公司在哪,哪条路,哪个大厦?

这个题目就需要随机应变了,比如:上家公司在北京大兴区,经济技术开发区,凉水河二街,大族企业湾,11号楼A座三层。

● 你上家公司是做哪个行业的?

这个题目需要大家查一下“之前工作的公司”,了解一下该公司主要做哪一方面的。如果上一家工作的公司是外包公司那是不错的。因为被外派出去的人员可能会接触不同行业的项目。

● 对你上家公司进行一个评价?

我相信面试官您也看到了,自从我大学毕业到现在一直在上家公司工作,这也充分证明了我对上家公司的认可。上家公司拥有良好的企业文化,为我们提供了良好的工作环境,我们团队也构建了一个良好的工作氛围,大家工作都很积极努力,团队成员也都很照顾我,如果还有机会回到石家庄工作的话,我希望能再回到这家公司。

● 说一下你的离职流程?

我离职的前1个月提出了申请,然后我们老大就开始招人,招到后,我就开始和新人进行工作交接,直到新人能够上手,我就离开了。

● 你们多少人开发这个项目?

● 说一下你们项目组的组织架构/人员分配?

● 你们分组了吗,都是什么组,你在哪一组?

● 你和领导在一些想法上产生了分歧,你怎么做?

在工作中,和领导打交道是一个技术活,让领导开心很重要,但也不能委屈了自己,当和领导产生分歧后,好尽量的去挽救双方之间的关系,毕竟自己使下属,在该让步的时候还是要学会让步。

第一:积极的沟通。也许是领导不了你的实际情况,没看到你的付出和努力,对你产生了误解,所以适当的沟通就很重要了。

第二:保持不卑不亢的态度。在产生分歧的时候,不要一味的退让或者太过于强势,凡是都是可以沟通的,让领导看到自己的工作态度很重要。

第三:显示出自己对领导的尊重。也许你的工作能力是比较出众的,但是一定要给足领导面子,让领导看出自己的态度,免得给领导留下了不好的态度。

第四:选择求同存异的处理手法。特别是解决工作上的问题,手段是有很多的,你考虑的方向和领导考虑的方向可能会有所出入,可以选择一种大家都认同的方法来处理。

第五:领导布置的任务要好好的完成。就算是和领导有分歧,但是领导布置的任务还是要好好的完成,这样可以显示出自己对工作一丝不苟的态度,也会的到领导的赞赏。

第六:在不改变自己原则的前提下妥协。先要表明自己的立场,让自己不做违背自己本心的事情,然后考虑妥协,对方是领导,很有可能是你处于被动的地步,所以适当的妥协是有必要的。

● 你们项目组使用的是哪个项目管理软件?

禅道。

● 你们项目组使用的是哪个版本控制工具?

最近两年的开发一直在使用Git,感觉Git比SVN好用。Git是基于分布式的。

● 你之前交过社保吗?

之前没有缴纳过社保,公司每个月有800元补助。(之前在北京工作过,并且在北京交过社保的同学,可以回答:交过社保。如果社保不是连续的,可以告诉面试官,社保中间断了,不想交社保了,公司每个月有800元补助。)

● 程序员苦逼的一天?

其它

● 你们的测试环境是怎样的?

我们的测试环境模拟的就是生产环境,只不过生产环境中服务器硬件要多一些,在测试环境中一个机器上会安装多个软件。

● AJAX跨域你是怎么实现的?

首先我先给您解释一下我理解的跨域,为什么会有跨域呢?这是因为浏览器的同源策略导致的,同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。它的核心就在于它认为来自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源。所谓同源是指:域名、协议、端口相同。所以跨域限制主要的目的就是为了用户的上网安全。不过在实际的开发中有很多情况下需要我们实现跨域访问,因为同一个项目的不同服务可能部署在不同的服务器当中,服务器A调用服务器B当中的资源时,就涉及到了跨域问题,那么怎么解决AJAX跨域呢?

第一种方式:JSONP方式解决跨域问题。

jsonp解决跨域问题是一个比较古老的方案(实际中不推荐使用),实际项目中如果要使用JSONP,一般会使用jQuery对JSONP进行了封装的类库来进行ajax请求。