当前位置:首页 > 开发 > 移动开发 > 正文

软件系统的稳定性

发表于: 2015-11-13   作者:互联网   来源:转载   浏览次数:
摘要: 软件系统的稳定性     软件系统的稳定性,主要决定于整体的系统架构设计,然而也不可忽略编程的细节,正所谓“千里之堤,溃于蚁穴”,一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃。这正是我阅读Release It!的直接感受。究其原因,一方面是程序员对代码质量的追求不够,在项目进度的压力下,只考虑了功能实现,而不用过多的追求质量属性;第二则是对编

软件系统的稳定性

 

stability

 

软件系统的稳定性,主要决定于整体的系统架构设计,然而也不可忽略编程的细节,正所谓“千里之堤,溃于蚁穴”,一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃。这正是我阅读Release It!的直接感受。究其原因,一方面是程序员对代码质量的追求不够,在项目进度的压力下,只考虑了功能实现,而不用过多的追求质量属性;第二则是对编程语言的正确编码方式不够了解,不知如何有效而正确的编码;第三则是知识量的不足,在编程时没有意识到实现会对哪些因素造成影响。

例如在Release It!一书中,给出了如下的Java代码片段:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.cf.flightsearch;
//...
public class FlightSearch implements SessionBean {
     private MonitoredDataSource connectionPool;
     public List lookupByCity(. . .) throws SQLException, RemoteException {
         Connection conn = null ;
         Statement stmt = null ;
         try {
             conn = connectionPool.getConnection();
             stmt = conn.createStatement();
             
             // Do the lookup logic
             // return a list of results
         } finally {
             if (stmt != null ) {
                 stmt.close();
             }
             if (conn != null ) {
                 conn.close();
             }
         }
     }
}

正是这一小段代码,是造成Airline系统崩溃的罪魁祸首。程序员充分地考虑了资源的释放,但在这段代码中他却没有对多个资源的释放给予足够的重视,而是以释放单资源的做法去处理多资源。在finally语句块中,如果释放Statement资源的操作失败了,就可能抛出异常,因为在finally中并没有捕获这种异常,就会导致后面的conn.close()语句没有执行,从而导致Connection资源未能及时释放。最终导致连接池中存放了大量未能及时释放的Connection资源,却不能得到使用,直到连接池满。当后续请求lookupByCity()时,就会在调用connectionPool.getConnection()方法时被阻塞。这些被阻塞的请求会越来越多,最后导致资源耗尽,整个系统崩溃。

releaseit

Release It!的作者对Java中同步方法的使用也提出了警告。同步方法虽然可以较好地解决并发问题,在一定程度上可以避免出现资源抢占、竟态条件和死锁的情况。但它的一个副作用同步锁可能导致线程阻塞。这就要求同步方法的执行时间不能太长。此外,Java的接口方法是不能标记synchronized关键字。当我们在调用封装好的第三方API时,基于“面向接口设计”的原理,可能调用者只知道公开的接口方法,却不知道实现类事实上将其实现为同步方法,这种未知性就可能存在隐患。

假设有这样的一个接口:

?
public interface GlobalObjectCache {
     public Object get(String id);
}

如果接口方法get()的实现如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
public synchronized Object get(String id){
     Object obj = items.get(id);
     if (obj == null ) {
         obj = create(id);
         items.put(id, obj);
     }
     return obj;
}
 
protected Object create(String id) {
     //...
}

这段代码很简单,当调用者试图根据id获得目标对象时,首先会在Cache中寻找,如果有就直接返回;否则通过create()方法获得目标对象,然后再将它存储到Cache中。create()方法是该类定义的一个非final方法,它执行了DB的查询功能。现在,假设使用该类的用户对它进行了扩展,例如定义RemoteAvailabilityCache类派生该类,并重写create()方法,将原来的本地调用改为远程调用。问题出现了。由于采用create()方法是远程调用,当服务端比较繁忙时,发出的远程调用请求可能会被阻塞。由于get()方法是同步方法,在方法体内,每次只能有一个线程访问它,直到方法执行完毕释放锁。现在create()方法被阻塞,就会导致其他试图调用RemoteAvailabilityCache对象的get()方法的线程随之而被阻塞。进而可能导致系统崩溃。

当然,我们可以认为这种扩展本身是不合理的。但从设计的角度来看,它并没有违背Liskove替换原则。从接口的角度看,它的行为也没有发生任何改变,仅仅是实现发生了变化。如果不是同步方法,则一个调用线程的阻塞并不会影响到其他调用线程,问题就可以避免了。当然,这里的同步方法本身是合理的,因为只有采取同步的方式才能保证对Cache的读取是支持并发的。书中给出这个例子,无非是要说明同步方法潜在的危险,提示我们在编写代码时,需要考虑周全。

分类:  设计之道

软件系统的稳定性

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
软件系统的稳定性,主要决定于整体的系统架构设计,然而也不可忽略编程的细节,正所谓“千里之堤,
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。 很久之前写的了,留着有点浪费,共
【原创】Android 系统稳定性 - ANR(二) 文章都为原创,转载请注明出处,未经允许而盗用者追究法律
概述: 此分享是关于"系统稳定性及性能优化",强调稳定架构,容量规划,运行监控和弱依赖。 技术点
概述: 此分享是关于"系统稳定性及性能优化",强调稳定架构,容量规划,运行监控和弱依赖。 技术点
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。 很久之前写的了,留着有点浪费,共
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。 很久之前写的了,留着有点浪费,共
以下内容是转至盛大创新研究院官方博客的一篇文章http://in.sdo.com/?p=1707,文中几乎涵盖了当今主
我们在之前给大家介绍了“现在起,全面了解你电脑的性能!硬件测试软件大搜罗 - 综合性能篇“,可以
Hardware Freak 是系统信息(尤其硬件信息)速查软件,可以查看电脑内的各类硬件信息以及CPU、显卡
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号