【.com速递】我们都会时不时地犯错……而且,有时我们会一下子犯很多错!GrzegorzZiemonski以愉快而坦率的方式加入我们,回顾他在调试关键Java应用程序版本时所犯的错误。DZone团队的MichaelTharrington最近向我建议,我应该写下我作为开发人员所犯的一些错误以及我从中吸取的教训。好吧,现在是做这件事的最佳时机——我的团队刚刚上线了一个关键的应用程序,所有可能出错的地方都出错了!当然,并不是下面给出的每个解决方案都完全是我写的——其中一些是我们在敏捷开发中结对编程时产生的,所有的一切都经过了严格的代码审查过程——这就是为什么有点让这个问题变得更可笑的原因。问题背景我们正在开发一个简单的Web应用程序,它公开一个RESTAPI以与外部提供者程序通信并安全地存储一些结果;这样,我们就不需要进行太多调用,因为我们必须为每个API调用付费。该应用程序主要依赖于SpringBoot、Web框架和数据功能。该应用程序的两个实例将部署在由负载平衡器支持的公司服务器上。错误1——进程并发错误调用外部提供者程序耗时长;自然地,我们的客户端应用程序都不愿意等待这种类型的调用。正因为如此,我们都同意改进后台处理——我们第一次调用它时,我们返回一条消息“DONT_KNOW_YET_COME_BACK_LATER...”。下次我们调用它时,我们会返回一个持久的结果。因此,自然会出现一个问题:如果我们在足够短的时间内两次调用相同的调用,会发生什么情况?灵感突然出现:我们必须以某种方式保护自己,避免使用相同的数据两次调用外部提供者程序。这是我最初的编程计划:privateSetcurrentlyProcessedIds=ConcurrentHashMap.newKeySet();//在代码中更进一步:if(currentlyProcessedIds.add(id){doTheJob(id);currentlyProcessedIds.remove(id);}你可以找到这段代码有什么问题?如果你不立即发现我的愚蠢错误,慢慢来。当然,如果doTheJob部分抛出异常,整个程序就会崩溃!这是一个典型的进程并发错误,导致在明显的内存损坏中!不幸的是,四个人盯着这段代码,但没有人注意到,我们实际上可以阻止id再次被正确处理。这是更正代码的正确版本:if(currentlyProcessedIds.add(id){try{doTheJob(id);}finally{currentlyProcessedIds.remove(id);}}错误2-负载均衡,但问题依旧如果你足够聪明,你可能已经注意到错误发生的地方了-上面那段还有代码有问题!我们有两个独立的实例部署在负载均衡器上的应用程序。这意味着问题不仅仅是并发,而是分布!目前,我们还没有实现分布式的解决方案,但是我们显然需要在两个应用程序实例之间同步当前处理的数据集。错误三——早上喝咖啡无意中发现性能问题后台处理的想法来自于我对遗留方案的观察。这种老套的方案严重依赖数据库的性能,但即使在最坏的情况下,它比外部调用更快。一开始,我们建议负责客户端应用程序的程序员可以允许第一次(长)调用超时,稍后再试。然而,在实践中,当整个系统负载很重时,这并不理想。我的任务是测量我们的应用程序响应时间范围需要多长时间。我在旧解决方案中找到了所有数据库查询,并针对我们的数据库一一进行了测试。我收集这些结果,做一些计算,***制作一个漂亮的表格并将其放在我们公司的wiki上。到底出了什么问题?好吧,我在早上喝咖啡时手动运行了查询,发现这次的系统性能与在重负载下运行所有??系统有很大不同。这意味着我之前的计算过于乐观,产品上线后首先看到的是客户端应用超时的“墙”。错误4——使用太少的测试数据现在,系统负载只是我们高估系统性能的原因之一。第二个原因更尴尬!我们的应用程序和客户端程序之间的所有测试都基于相当有限的数据集——大约1000条记录。结果似乎是成功的,因为在测试期间没有出现任何警告信号。其实我们忽略了一个小细节,那就是:在系统上线之前,我们用从旧方案迁移过来的数据填充到数据库中——这个数据大约是100万条记录!数据集比原来大了三个数量级!那是我们发现自己忘记设置关键数据库索引的时候——这是您在关键应用程序上线之前喜欢做的事情!错误5——测量不是统计数据商界要求我们根据我们对外部供应商计划的请求准备一份报告。因为我们打了很多电话而且很贵,所以我们想为他们提供一种方法来计算预期成本并验证我们从供应商那里得到的发票。当然,业务人员不懂SQL,因此他们要求将Excel报告通过电子邮件发送给他们。哦,我的母亲...要求我们生成一个Excel文件并通过电子邮件发送?现在是2016年。真的没有办法!最后,我们还是提供了一个漂亮的接口来实现统计措施。以后我们还会增加一个请求次数的计数器!因为我们遇到了如上所述的那些初始问题,所以我们发布了一些修补程序并再次发布了应用程序。重新部署后,显示计数器的仪表板看起来很奇怪。请求数量发生了什么变化?情况是:测量数据保存在应用端,定时发送给测量服务器。这意味着,每次我们重新启动应用程序时,计数器的值都会消失。简单就是废话!幸运的是,我们有一种方法可以提供有关请求的正确信息,而无需在仪表板上使用漂亮的计数器,但我们仍在尝试实现一个真正的计数器来保存业务统计信息。总结就在我们的产品终于上线之前,我曾经跟同事说:我有点担心,因为从立项到测试阶段,没有什么大的问题,一切看起来都是那么的顺利,有没有重大障碍。事实证明我是对的,错误的事情一定会发生!虽然我在这篇文章中提到的错误现在看起来都很明显,但当我们急于开发和测试时它们并不那么明显。现在,把我们项目开发的这些害羞的事情写出来有点尴尬;但是,我希望作为读者的您至少能从中获得一些乐趣,并且以后不要再犯同样的错误!【翻译稿件,合作网站转载请注明原译者和出处.com】