如何解决不可复制/随机发生的错误?


11

我们有一个多语言网站,几天前在其中发现了一个错误。它以其他语言显示其他语言数据,并且还选择了英语之类的混合数据,但同时还在页面中显示其他语言数据,反之亦然。它很少执行此操作,但是它存在于网站中。遍历代码也无济于事,因为这种情况并非总是如此。

有什么建议可以及时发现问题?我在这里要求策略。


4
开始探查可能导致此错误发生的情况的代码(而不是相反地进行)
Imran Omar Bukhsh 2011

Answers:


20

第一步是尝试确定可能导致此类问题的原因。由于这与为代码部分选择正确的语言有关,因此请考虑以下因素:

  • 如何检测语言? 它基于HTTP请求中的信息吗?是基于会话信息?还是基于数据库字段?从本质上讲,这可能是与您的应用如何选择每个部分的语言有关的问题吗?
  • 语言如何显示? 您是从属性文件还是数据库中提取数据?是否有可能丢失对正确语言的引用?您看到的混合语言是否始终是网站的默认语言?
  • 与客户端环境相关吗? 这与第一个项目符号有关,但范围更广。由于下游缓存代理,我遇到了奇怪的渲染问题。通常,这些类型的问题是整页过时的页面或将一个人的页面提供给其他用户的页面(令人尴尬)。
  • 您是否正在使用线程局部值? 如果在多个线程中处理了一个请求,则线程本地值将基于当时正在工作的线程而具有不同的信息。在Web服务器环境中,您不能假定开始处理的线程将与完成处理的线程相同,除非这是平台规范的一部分。服务器作者发现,如果他们重用一个小的线程池并以块的形式多路复用它们,则他们可以同时处理更多的请求。即使从请求的开始到结束都有一个线程,服务器也可能同时将其他请求复用到该线程上。可以考虑将该值绑定到请求或会话属性,而不是线程本地变量。

现在,一旦你已经表征了可能性的什么可以去错了,它的时间,以确保你有你需要尝试,并找出数据没有出错。

  • 在问题区域周围使用大量日志记录。这是Log4J或Log4Net之类的工具真正发挥作用的地方。该日志记录框架以及其他类似的框架允许您打开某些类别的日志记录,同时降低其他所有内容的噪音-所有这些都可以通过更改配置文件来实现。您想引入新的日志记录语句来确定您怀疑的问题是否可能是问题所在。另外,请确保您的HTTP访问日志具有您想要的有关每个请求的所有信息(cookie,http标头参数等)。
  • 尝试模拟问题。由于这种情况是偶发发生的,因此发生时服务器上的负载是什么样的?您是否同时收到来自多种语言的大量请求?如果是这样,请尝试在测试环境中模拟这种负载。您可能需要与JMeter类似的工具。您还希望能够为假客户端欺骗IP地址。请记住,IP地址是分开分配的,因此您可以根据地址的前两个部分来确定IP所在的国家/地区。
  • 在您的测试环境中,该问题将是偶发性的,但是当您缩小真正原因的范围时,您就可以歪曲结果,使其比实际情况频繁地发生。此外,您可以更轻松地查看日志文件并尝试从中学习。
  • 这是一个反复的过程,因此请耐心等待。您必须诱导您认为将重现该错误,检查日志并根据发现的内容优化测试的负载类型。重要的是要确定问题,因此要抵制进行一些简单修复的冲动,这些修复可能只会使真正的问题发生的频率降低。

最后,一旦将问题缩小到知道如何重现问题以及导致问题的原因,就可以编写最小的自动化测试,以强制代码解决问题。如果您将问题缩小为一个类,或者一对类不能正常工作,请在该级别重现该问题。您不必生成100个线程即可,只需进行最小的测试即可导致问题100%发生。

现在,您可以修复它,并有足够的信心确保它不会再咬您。


10

该错误并非不可复制。您只是还没有找到如何复制它。

除非您根据某些Random()语句的返回值引发异常,否则没有错误是随机的。

我知道这看起来像是语义,但在心理上告诉自己这是令人放心的。

找出如何再现仅由于复杂的比赛条件或类似情况而发生的错误非常困难且令人沮丧。

至于如何找到它,我将在可能为您提供更多信息的地方打开/向应用程序添加一些日志记录。

接下来,告诉看到该错误的人员(无论是Devs,QA还是最终用户),请在看到错误后立即报告该错误的发生时间,然后查阅您的日志。向他们询问其他信息,并且错误可能仅由于几个不同系统的交互作用或由于竞争条件而发生

希望您能够找到潜在客户。


甚至Random()调用也不是真正随机的,除非它们是从硬件白噪声生成器派生的。它们是伪随机的,这意味着数字在数学上以尽可能随机的顺序分布。但是,如果您从相同的“种子”值开始,则每次都会获得相同的答案。
Berin Loritsch 2011年

1
@Berin:我知道。
Gilles

+1表示“您还没有找到如何再现它的方法”。所有错误都有根本原因,否则将不会发生。
Mike S

1
它不一定非要使用Random(),它与时间有关,尤其是那些涉及对共享资源的不当访问的事物,很难重现。
罗伦·佩希特尔

2
@吉尔斯:除非它们可能不确定您可以合理衡量的任何事物。(说,正是其他一些任务发布的时间片。)
Loren Pechtel 2012年

5

您可以尝试在代码中查找可以识别出问题发生的位置(例如,方法中的参数不一致),将检查添加到代码中,然后让它们向调试日志中添加额外的信息(例如堆栈跟踪,对象)添加到会话等)

运气好的话,您可以捕获有关事件的信息并推断出解决问题的方法。


2

如果重现有时失败的相同步骤,请将其自动化并放入循环中,自动化应该会有所帮助。运行50,000次,很可能会发生。


该事件不是随机的,只是随机的。这样做可能会使它出现,但是却很少给您提供有关它为何出现的信息。
Josh K

1
@Josh-如果他无法复制它,例如,这可能是一种很好的方法,并且可以获得带有调试符号的堆栈跟踪。我认为这是一个伟大的第一步-亲眼目睹
Kieren Johnstone

您假设有一个堆栈并且可以获取。他没有提供任何有关该应用程序的技术信息,也没有提供在这种负载下进行调试的可访问性。这不是调试策略,这是用锤子试图抓住它破裂的确切时间的方法。
乔什K

@Josh-我的实际经验告诉我,调查/修复错误中最有价值的事情就是亲眼目睹。无论您看到的是带有定时的东西,堆栈跟踪,日志中的东西还是其他任何东西。在可能的情况下,在循环中测试了看似随机发生的问题确实使我很快就到了那里。如果您有不同的想法,请为基督的缘故将其发布为答案-这是有效的方法,也是有效的答案。
Kieren Johnstone

我不同意,我相信贝林的答案是解决这个问题的正确方法。
Josh K

1

尝试寻找模式来确定导致此问题显现的条件。这应该使您指向代码失败(或行为不一致)的部分。


没什么..............
theringostarrs 2015年

0

当问题可以检测正在发生?如果是这样,您可以可靠地转储有关系统状态的信息吗?

如果这两个问题的答案都是肯定的,请检测代码以实际记录错误发生时的尽可能多的信息,然后等待。

这不能替代其他人的建议(您仍然需要通过代码如何进入所看到的状态来进行推理),但是只要您无法随意重现该错误,最好不要浪费它出现的机会。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.