当前位置:首页 > 发言稿 > [分布式系统开发优化策略]java分布式系统开发
 

[分布式系统开发优化策略]java分布式系统开发

发布时间:2019-01-10 04:22:14 影响了:

  摘要:随着网络、集群和并行技术的广泛应用,分布式系统应用越来越多,如何开发高效的的分布式系统已成为当今软件工程研究的重点。本文就分布式系统开发提出了五种优化策略,为开发科学、高效、实用的分布式系统将起到一定的指导作用,也使得开发分布式系统变得更容易。
  关键词:分布式系统;伸缩性;性能;优化策略
  中图分类号:TP302文献标识码:A文章编号:1009-3044(2007)18-31607-02
  The Strategy of Optimization for Development of Distributed System
  DU Cheng-long,LONG Shao-jun
  (Hubei Professional College of Land Resource,Jingzhou 434002,China)
  Abstract:With the widespread application of network,clustering and parallel technology,there are more and more distributed system to use.It is more important to how to develop a efficient distributed system in soft engineering. Five kinds of optimization strategy are proposed it will play guidance function to develop scientific, high-efficient and practical distributed system .So it become easy to develop a distributed system.
  Key words:Distributed system;Elasticity;Performance;Optimization strategy
  
  1 引言
  
  分布式系统的特点是让几个物理上独立的组件作为一个单独的系统协同工作,在此做了如下的假定:如果一台计算机能够在5秒钟内完成一项任务,那么5台计算机以并行的方式一起工作时就能在1秒钟内完成一项任务。当然,分布式系统编程不会如此简单。问题就在于“以并行方式协同工作”,很难让网络中的5台计算机高效协作。实际上,要达到如此高效,应用软件必须经过特殊设计。例如,马是强大的动物,但是从力量与重量之比来说,蚂蚁要比马强壮很多倍,假设强壮10倍,如果聚集了与一匹马质量相同的一堆蚂蚁并利用它们来工作,则可以拉动10倍于一匹马所能拉的货物。这就是一个非常好的分布负载示例,这种计算是合理的,让数百万的蚂蚁去拉一个货物却又是不现实的。但可能通过优化编程让系统运行效率达到最大化。
  
  2 应用程序的分层
  
  分布式计算提出几台计算机协同工作的问题。这也是将应用程序分解为几个可被分布式处理的任务的问题。经过这些年的发展,可以清楚地了解到大多数应用程序是由3个主要逻辑部分构成:表示逻辑,业务逻辑和数据源逻辑。
  (1)表示逻辑:表示逻辑是应用程序的一部分,终端用户可以能过它输入订单、查找用户信息和查看业务报表。
  (2)业务逻辑:这部分是应用程序的的中心,开发人员将在这里花费大部分的时间和精力。它包括定义业务运行方式的业务规则。例如,业务逻辑规定客户何时收到折扣、如何计算运费以及订单上所必需的信息。
  (3)数据源逻辑:这部分逻辑用于保存将来可能用到的的订单、客户信息以及其他一些信息。幸运的是,SQL Server和Oracle等数据库产品会完成大部分工作。不过仍然需要设计数据层以及检索数据所使用的查询。
  请不要想当然地认为每一层必须运行在单独的机器上或单独的进程中。每一层的代码只能通过定义良好的界面与另一层的代码进行交互。在此要先弄清楚可伸缩性与性能的概念。
  
  3 可伸缩性与性能问题
  
  可伸缩性与性能相关,但它们并不相同。性能是用于测量当前系统运行的速度,表现在吞吐量。可伸缩性是用于测量当前系统中增加资源时的性能改善,资源指CPU、内存或计算机等。两者之间的关系如图1所示。
  图1 可伸缩性与性能相关
  可伸缩性有两种伸缩方式:
  (1)垂直伸缩:当使用新的、快速的硬件取代慢速硬件时,例如将Pentium 500 换成Pentium 1G,就是垂直伸缩。对于没有经过良好设计的应用程序,垂直伸缩是惟一可进行扩展的方式。然而,垂直伸缩相对昂贵并且容易产生错误。
  (2)水平伸缩:当为现有的应用程序添加额外的、负载均衡的服务器时,即可实现水平伸缩。这种伸缩可保护当前的硬件资源,并且如果其他的服务器损坏,它也会为应用程序提供相应的故障保护。在硬件方面,水平伸缩相对较便宜,但是应用程序必须进行合理的优化才能进行水平伸缩。
  图2 性能与可伸缩性的优化对比
  一些短期内优化性能的技术从长远观点看可能会削弱可伸缩性。请看图2中两个应用程序的比较。第一个应用程序在牺牲可伸缩性的基础上优化了性能。第二个则优化了可伸缩性。最初,性能被优化的应用程序执行良好,它是以昂贵的硬件资源替换来提高吞吐量的。然而,当添加额外的硬件时,应用程序所必要的稳定性就开始影响其吞吐量。很快它就达到了平稳状态,同时可伸缩的应用程序的吞吐量却会继续提高。
  由此看出,在优化可伸缩性的基础上提高性能的应用程序才是科学有效的分布式应用系统。下面提出了五大优化策略。
  
  4 五大优化策略
  
  分层结构允许在不影响其它层的情况下修改某一层的实现。同时,也允许将来从物理上灵活地分隔各个层。但是,不应该轻易决定在独立进程或机器上执行每一层。如果您决定对某一层进行分布处理,那么必须对它进行特殊的分布设计。下面几项用于有效分布应用程序的策略以及使用这些策略的理由。
  4.1保守分布
  对于分布式编程来说,这个策略看起来让人有些惊奇。然而,这项策略却是基于计算中一个简单且不可否认的事实:调用不同进程上对象的方法要比调用进程内对象的方法慢数百倍;将对象移动到网络中的另一台计算机上,这种方法调用又会慢数十倍。
  那什么时候才应当进行分布式处理呢?回答是只有必须进行分布时才这样做。从数据层开始考虑。
  当决定使用数据库时,一般需要决定分布数据源逻辑。通常,数据库运行在独立的专用服务器上----换句话说,它相对于其他层是分布式的。这样做的理由:数据库软件复杂而昂贵,通常需要高性能的硬件,设计在独立的物理层上即可降低成本又可提高运行效率。
  然而,决定分布表示逻辑会更复杂一些。首先,除非所有应用程序用户都使用公共的终端(例如ATM),否则表示层的某些部分就必须分布到每个用户机上。但问题是分布到什么程度。近来的趋势是在服务器上执行大部分逻辑,而将简单的HTML发送到客户端Web浏览器。这实际上是遵守了保守分布的原则。
  实际上有许多分布选项。分布的时间、原因以及如何分布等受到很多因素的影响---其中的许多因素又互相竞争。下面几个策略会提供进一步的指导。
  4.2本地化相关内容
  如果决定或被迫分布全部或部分业务逻辑层,那么应当保证经常交互的组件被放置在一起。换句话说,应当本地化相关内容。例如,参考图3 所示的电子商务应用。这个应用程序将客户组件、商品组件和购物车组件分隔到指定的服务器上,这会在表面上允许并行执行。然而,当一件商品添加到购物车时,组件之间就会进行多次交互。每一次交互都会带来跨网络方法调用的系统开销。因此,这种跨网络的行为会抵消掉并行处理带来的好处。再考虑到几千用户会同时使用,可想其后果是破坏性的。
本文为全文原貌 未安装PDF浏览器用户请先下载安装 原版全文   在本地化相关内容的同时,如何利用分布式编程(也就是并行处理)的作用呢?可以使用负载平衡方法将每个客户机请求路由到特殊的服务器,即如图4 所示的这种结构。基于Web的应用程序经常通过在几个Web服务器上驻留相同的Web站点来使用这种模型,有时该设置被称为Web场。
  对应用程序服务器进行复制和均衡负载可以很好地提高应用程序的容量或可伸缩性。然而,你需要非常清楚如何管理状态,下一策略可以提供参考。
  图3 一个不成功的分布式应用例子
  4.3优先选用无状态对象,而不是有状态对象
  如果想利用在图4 中显示的负载平衡体系结构,需要仔细管理分布式对象中的状态,或者干脆不使用状态。
  在此尽可能简洁地定义无状态对象:它是能够在方法调用之间被安全创建和销毁的对象。应用程序在方法调用之后销毁无状态对象,不会影响到其它用户。因此要对该类进行特殊实现,这样的类才不会和其它类有依赖关系。
  图4 一个成功的分布式应用示例
  有两个原因可说明有状态对象对于可伸缩性具有负面的影响。首先,有状态对象通常会在服务器上存在很长一段时间。在它的生存期中,它会聚集并使用服务器资源。这样即使有状态对象不工作或正在等待其他用户的请求,它也会阻止其他对象使用这些资源。虽然一些人认为内存是资源竞争中的关键资源,但实际上这只是相对次要的因素。如图5所示,有状态对象是耗费稀有资源(例如数据库连接)的真正罪魁祸首。
  图5 计算机资源的相对数量
  有状态对象对可伸缩性具有负面影响的第二个原因是它们最小化了跨越多个服务器对应用程序进行复制和负载平衡的效率。考察图示6的场景。将图示6看作是应用程序在某一时间点的快照。在该快照之前系统的负载很重。然而,在快照时间点许多用户已离开,只有三个客户机仍与系统进行连接。不过,应用程序使用了有状态对象,并且在系统重负载期间,所有的三个对象都被创建在服务器A上。现在,即使服务器B完全闲置,从客户机传输过来的请求也必须被发送到负载很重的服务器A上,因为在服务器A上保存着客户状态。如果这个应用程序使用了无状态对象,那么负载平衡器会直接将客户请求传递到负载最轻的服务器上,而不用考虑以前使用的是哪个服务器。
  图6 有状态对象在负载平衡的环境下不能很好地工作
  通过使用智能缓存、会话管理和负载均衡的方法,可以避免或者最小化使用有状态对象所带来的问题。这也是本策略选用无状态对象的原因,但不是必须使用。这里需要再次说明,这个策略只能应用于为在其他进程或机器中执行的代码所提供的对象。
  4.4尽量使用“粗粒度”接口
  面向对象编程的思想之一是创建具有许多简单方法的对象,每一个方法都专注于一个特殊的行为。考虑下面的Customer类。
  Class Customer
  {public string Name() {get;set;}
  public string Email(){get;set;}
  public void Create();
  public void Save();}
  这种实现会受到大多数面向对象专家的肯定。但是我的第一反应是:相对于调用代码而言该对象在何处运行。如果直接在过程中访问Customer类,这种设计是非常正确的。如果这个类被执行在其他过程或机器中的代码所调用,这种设计却是非常糟糕的。具体原因请看下面代码,设想它正运行在客户机上,而Customer对象运行在服务器上,该代码的每个属性和方法都要跨进程或跨网络进行遍历,这将会产生很严重的性能问题。
  Static void ClientCode()
  {Customer cust=new Customer();
  cust.Create();
  cust.Name= "杜成龙";
  cust.省略 ";
  cust.Save();}
  这个Customer类具有典型的“细粒度”接口。下面是具有“粗粒度”接口的Customer类。
  [Serializable]
  class CustomerData
  {public string Name() {get;set;}
  public string Email() {get;set;}}
  class Customer
  {public void Create(CustomerData data);
  public void Save(CustomerData data);}
  初看这段代码,它将“细粒度”接口从Customer类移到了Customerdata类中。这样做有什么好处?由Serializable特性可知,只要CustomerData对象越出进程边界就复制整个对象。因此,当客户机代码调用CustomerData类的属性时,实际上在访问一个本地对象。
  可以看出,这段代码不如第一个Customer类那么清晰。但是相对于前者所具有的更多面向对象的特点而言,当Web站点的访问量突然变大,以至于需要扩充容量来满足新用户的访问时,后者却会提供更多的保护。因此,在此建议哪怕是被进程外代码偶尔访问的对象也应当被设计成“粗粒度”接口。
  要记住,这条策略也只能适用于分布在边界上并可能跨越进程边界的对象。而进程内的对象则可以自由地使用,不受此限制,也不会危及应用程序的可伸缩性或性能。
  4.5采用接口编程技术,而不是具体实现的编程
  目前接口编程在分布式编程领域得到了广泛的共识。它解决的问题与性能或可伸缩性无关。接口编程在团队同步开发中发挥着至关重要的作用,并且提供了更简单的访问方式,从而可以减少频繁的且时常出问题的部署。目前用得非常火热的COM技术就是完全基于接口的。
  
  5 结束语
  
  基于分布式系统的特殊要求,采用以上五种优化策略,对开发出科学、高效、实用的分布式系统将起到指导性作用,这也会使得开发分布式系统变得更容易。
  
  参考文献:
  [1]苏洋.Java分布式应用程序设计[M].北京希望电子出版社,2002.7.
  [2]Marko Boger .Java与分布式系统[M].机械工业出版社,2003.4.
  [3]TOM BARNABY. .NET分布式编程[M].清华大学出版社,2004.4
  注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
本文为全文原貌 未安装PDF浏览器用户请先下载安装 原版全文

猜你想看
相关文章

Copyright © 2008 - 2022 版权所有 职场范文网

工业和信息化部 备案号:沪ICP备18009755号-3