Web站点崩溃的原因总结

2008-02-23 08:21:09来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

有许多种原因可能导致Web站点无法正常工作,这使得系统地检查任何问题变得很困难。下面将集中分析总结导致Web站点崩溃的最常见的问题。假如能够解决这些常规问题,那么也将有能力对付出现的一些意外情况。

磁盘已满

导致系统无法正常运行的最可能的原因是磁盘已满。一个好的网络管理员会密切关注磁盘的使用情况,隔一定的时间,就需要将磁盘上的一些负载转存到备份存储介质中(例如磁带)。

日志文档会很快用光任何的磁盘空间。Web服务器的日志文档、SQL*Net的日志文档、JDBC日志文档,连同应用程式服务器日志文档均和内存泄漏有同等的危害。能够采取措施将日志文档保存在和操作系统不同的文档系统中。日志文档系统空间已满时Web服务器也会被挂起,但机器自身被挂起的几率已大大减低。

C指针错误

用C或C 编写的程式,如Web服务器API模块,有可能导致系统的崩溃,因为只要间接引用指针(即,访问指向的内存)中出现一个错误,就会导致操作系统终止任何程式。另外,使用了糟糕的C指针的Java模拟量(analog)将访问一个空的对象引用。Java中的空引用通常不会导致立即退出JVM,但是前提是程式员能够使用异常处理方法恰当地处理错误。在这方面,Java无需过多的关注,但使用Java对可靠性进行额外的度量则会对性能产生一些负面影响。

内存泄漏

C/C 程式还可能产生另一个指针问题:丢失对已分配内存的引用。当内存是在子程式中被分配时,通常会出现这种问题,其结果是程式从子程式中返回时不会释放内存。如此一来,对已分配的内存的引用就会丢失,只要操作系统还在运行中,则进程就会一直使用该内存。这样的结果是,曾占用更多的内存的程式会降低系统性能,直到机器完全停止工作,才会完全清空内存。

解决方案之一是使用代码分析工具(如Purify)对代码进行仔细分析,以找出可能出现的泄漏问题。但这种方法无法找到由其他原因引起的库中的泄漏,因为库的源代码是不可用的。另一种方法是每隔一段时间,就清除并重启进程。Apache的Web服务器就会因这个原因创建和清除子进程。

虽然Java本身并无指针,但总的说来,和C程式相比,Java程式使用内存的情况更加糟糕。在Java中,对象被频繁创建,而直到任何到对象的引用都消失时,垃圾回收程式才会释放内存。即使运行了垃圾回收程式,也只会将内存还给虚拟机VM,而不是还给操作系统。结果是:Java程式会用光给他们的任何堆,从不释放。由于要保存实时(JustInTime,JIT)编译器产生的代码,Java程式的大小有时可能会膨胀为最大堆的数倍之巨。

更有一个问题,情况和此类似。从连接池分配一个数据库连接,而无法将已分配的连接还回给连接池。一些连接池有活动计时器,在维持一段时间的静止状态之后,计时器会释放掉数据库连接,但这不足以缓解糟糕的代码快速泄漏数据库连接所造成的资源浪费。

进程缺乏文档描述符

假如已为一台Web服务器或其他关键进程分配了文档描述符,但他却需要更多的文档描述符,则服务器或进程会被挂起或报错,直至得到了所需的文档描述符为止。文档描述符用来保持对开放文档和开放套接字的跟踪记录,开放文档和开放套接字是Web服务器很关键的组成部分,其任务是将文档复制到网络连接。默认时,大多数shell有64个文档描述符,这意味着每个从shell启动的进程能够同时打开64个文档和网络连接。大多数shell都有一个内嵌的ulimit命令能够增加文档描述符的数目。

线程死锁

由多线程带来的性能改善是以可靠性为代价的,主要是因为这样有可能产生线程死锁。线程死锁时,第一个线程等待第二个线程释放资源,而同时第二个线程又在等待第一个线程释放资源。我们来想像这样一种情形:在人行道上两个人迎面相遇,为了给对方让道,两人同时向一侧迈出一步,双方无法通过,又同时向另一侧迈出一步,这样还是无法通过。双方都以同样的迈步方式堵住了对方的去路。假设这种情况一直持续下去,这样就不难理解为何会发生死锁现象了。

解决死锁没有简单的方法,这是因为使线程产生这种问题是很具体的情况,而且往往有很高的负载。大多数软件测试产生不了足够多的负载,所以不可能暴露任何的线程错误。在每一种使用线程的语言中都存在线程死锁问题。由于使用Java进行线程编程比使用C容易,所以Java程式员中使用线程的人数更多,线程死锁也就越来越普遍了。能够在Java代码中增加同步关键字的使用,这样能够减少死锁,但这样做也会影响性能。假如负载过重,数据库内部也有可能发生死锁。

假如程式使用了永久锁,比如锁文档,而且程式结束时没有解除锁状态,则其他进程可能无法使用这种类型的锁,既不能上锁,也不能解除锁。这会进一步导致系统不能正常工作。这时必须手动地解锁。

服务器超载

NetscapeWeb服务器的每个连接都使用一个线程。NetscapeEnterpriseWeb服务器会在线程用完后挂起,而不为已存在的连接提供任何服务。假如有一种负载分布机制能够检测到服务器没有响应,则该服务器上的负载就能够分布到其他的Web服务器上,这可能会致使这些服务器一个接一个地用光任何的线程。这样一来,整个服务器组都会被挂起。操作系统级别可能还在不断地接收新的连接,而应用程式(Web服务器)却无法为这些连接提供服务。用户能够在浏览器状态行上看到connected(已连接)的提示消息,但这以后什么也不会发生。

解决问题的一种方法是将obj.conf参数RqThrottle的值配置为线程数目之下的某个数值,这样假如越过RqThrottle的值,就不会接收新的连接。那些不能连接的服务器将会停止工作,而连接上的服务器的响应速度则会变慢,但至少已连接的服务器不会被挂起。这时,文档描述符至少应当被配置为和线程的数目相同的数值,否则,文档描述符将成为一个瓶颈。

数据库中的临时表不够用

许多数据库的临时表(cursor)数目都是固定的,临时表即保留查询结果的内存区域。在临时表中的数据都被读取后,临时表便会被释放,但大量同时进行的查询可能耗尽数目固定的任何临时表。这时,其他的查询就需要列队等候,直到有临时表被释放时才能再继续运行。

这是个不容易被程式员发觉的问题,但会在负载测试时显露出来。但可能对于数据库管理员(DataBaseAdministrator,DBA)来说,这个问题十分明显。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 用IE的Web服务建立ASP.NET应用程式(四)

下一篇: 一五一十谈IIS安全机制