一步一步理解Java 企业级应用的可扩展性

老实说,“可扩展性”是个全面且详尽的话题,而且往往得不到充分理解。人们通常认为可扩展性等同于高可用性,笔者见过编程新手和架构师“老手”都建
议将集群作为可扩展性和高可用性的解决方案。建议确实没错,但问题是,人们通常是通过互联网搜索,而非实际理解应用本身的情况来实现集群。

笔者并未自称“专家”,只想通过这篇文章介绍一些有关 Java 企业级应用的一般扩展策略。

问题

可扩展性并非 Java
企业级平台规范内的标准组件。相关技术通常因供应商(应用服务器)而异,并且往往需要使用不止一款产品(应用服务器本身除外)。正因如此,设计可扩展的
Java 企业级应用才会有些棘手,要完成任务,往往不仅没有可以参照的实例,而且要求我们必须彻彻底底地理解应用。

扩展类型

笔者确信你们不是第一次看到这些内容。扩展一般分为两大类:纵向扩展,和横向扩展。

扩展的第一个自然阶段是纵向扩展。

  • 纵向扩展:包括给服务器增加更多资源,例如内存 (RAM)、磁盘空间、处理器等。这在某些方案中具备实用价值,但经过特定时间点后就会发现,这种扩展费用高昂,不如借助横向扩展。
  • 横向扩展:在这个过程中会增加更多机器或额外的服务器实例/节点,这也叫做集群(Clustering),因为所有服务器是作为一个集体或集群一起运行的。

高可用性不等于可扩展性

系统高度可用(拥有多个服务器节点以方便故障转移),并不表示系统可扩展。高可用性只是意味着,如果当前处理节点崩溃,请求会传递或转移到集群中的

另一个节点,以便从开始处继续。可扩展性则是通过增加可用资源(内存、处理器等)而提升系统特定性能(例如用户数量、吞吐量、响应时间)的能力,即使将失
败请求传递到另一个节点,也无法保证应用会在这种场景中正确运行(原因我们会在下面揭晓)。

下面我们来了解一些关于可扩展性的观点和相关讨论。

让横向扩展的集群达到负载均衡

假设您已经纵向扩展至最大容量,现在又用多个节点形成集群,将系统进行了横向扩展。接下来您要做的可能是在集群基础架构前放置一台负载均衡器,让负载分散在集群各部分之间(如果要详细了解负载均衡,大家可以参考其他方面的资料,在这里我们重点还是说扩展问题)。

应用有状态还是无状态?

现在你已经横向扩展了,这就够了吗?如果你的应用无状态,即应用逻辑在处理请求时不依靠现有服务器状态,则横向扩展已经足够。

但如果应用具有 HTTP 会话对象、有状态 EJB、会话域 bean (CDI、JSF)
等组件时,又会怎样?这取决于具体客户(具体来说,即调用线程),存储特定状态并依靠当前显示的状态来执行请求(例如,HTTP
会话对象可能会存储用户的身份验证状态、购物车信息等)。

在横向扩展或集群式应用中,节点的任何集群都可能为后续请求提供服务。如果首个请求的 JVM 实例处的状态数据没有被接收,其他节点会如何处理请求?

会话保持

会话保持配置可在负载均衡器层面上完成,确保来自特定客户/终端用户的请求始终被转发到同一个实例/应用服务器节点,即维持服务器亲和力。这样,我
们就缓解了所需状态无法显示的问题。但这里有个陷阱 –
如果节点崩溃怎么办?状态会被破坏,用户会被转至服务器请求处理所依赖的、但不具备现有状态的实例。

集群复制

为解决上述问题,您可对应用服务器集群机制进行配置,以支持有状态组件的复制,借此可确保 HTTP
会话数据(和其他有状态对象)显示在所有服务器实例上。如此一来,终端用户请求便可转至任何服务器节点,即使某个服务器实例崩溃或不可用,集群中的其他任
何节点都能够处理请求。现在您的集群就不是一般集群了,而是复制集群。

集群复制特定于 Java 企业级容器/应用服务器,最好查阅相关文档,了解如何复制集群。一般而言,大多数应用服务都支持 Java 企业级组件(如有状态和无状态的 EJB、HTTP 会话、JMS 队列等)集群。

然而这造成了另一个问题 – 应用服务器中的每一个节点都处理会话数据,导致 JVM 堆内存越来越多,因此垃圾回收也越来越频繁,另外,复制集群时还会消耗一定的处理能力。

有状态组件的外部存储

在另一层存储会话数据和有状态的对象,这可以借助 RDBMS 实现,大多数应用服务器本身就支持这一功能。

你可能已经注意到了,我们已经将存储从内存层转移到持久层 –
一天工作结束时,你可能会遇到由数据库导致的扩展问题。不是说这一定会发生,但数据库确实可能因为应用而过载,而后逐渐延时(例如在故障转移时)。设想一
下,从数据库中再现整个用户会话状态以便用在另一个集群实例中,不仅耗费大量时间,还会影响峰值负载下的终端用户体验。

最后的边界:分布式内存中缓存

这是最后的边界,至少在我看来如此,因为它把我们带回了内存方法。没有比这更好的办法了!Oracle Coherence、Hazelcast
这类产品或其他任何分布式缓存/内存网格产品可用于清理有状态的状态存储和复制/分布 – 这就是缓存层。好的一面是这些产品大多默认支持 HTTP
会话存储。

这种结构设置意味着,应用服务器的重启不会影响现有用户会话 – 给系统打补丁而不造成宕机和终端用户断电(虽然并不像听上去那么容易,但显然是个办法!),这始终是好事。总的来说,其理念是:应用层和 web 会话缓存层可独立运行和扩展,彼此不受干扰。

分布式不等于重复式

这两个词之间存在巨大差异,就缓存层而言,理解其中的差异是极为关键的。两者各有长短:

  • 分布式:缓存共享数据的各个部分,即数据集被分在各缓存集群节点之间(利用与产品特定的算法)。
  • 重复式:所有缓存节点都拥有所有数据,即每个缓存服务器都包含整个数据集的一份复本。

延伸阅读(主要关于 Weblogic)

结束语

  • 高度可扩展性可能不是所有 Java 企业级应用的必要条件。但如果你打算构建互联网/面向大众的应用,将高可扩展性纳入设计因素显然非常实用。
  • 对于希望充分利用自动灵活性(经济可行!)和高可用性等云平台(主要是PaaS)特点的应用而言,可扩展的设计是必要的。
  • 不难发现,有状态的应用通常更难以扩展。完全「无状态」或许无法实现,但我们应当朝这方面努力。

你用哪些技巧和方法来扩展 Java 企业级应用,快来和大家分享吧。

来源:51CTO

时间: 2024-09-27 16:51:26

一步一步理解Java 企业级应用的可扩展性的相关文章

一步一步理解 Java 企业级应用的可扩展性

摘要:本文主要介绍如何理解 Java 应用的扩展方式以及不同类型的扩展技术和具体技巧,介绍一些有关 Java 企业级应用的一般扩展策略. 老实说,"可扩展性"是个全面且详尽的话题,而且往往得不到充分理解.人们通常认为可扩展性等同于高可用性,笔者见过编程新手和架构师"老手"都建议将集群作为可扩展性和高可用性的解决方案.建议确实没错,但问题是,人们通常是通过互联网搜索,而非实际理解应用本身的情况来实现集群. 笔者并未自称"专家",只想通过这篇文章介绍

一步一步用JBuilder4开发EJB(转自china-pub)

一步一步用JBuilder4开发EJB 作者:廖家序 发布时间:2001/02/07 文章摘要: 本文提供一个步骤,通过简单的例子介绍怎样在JBuilder4的集成开发环境下开发EJB.这些步骤都很简单,对于了解EJB体系结构和一般的编程规则的人很容易理解.目的是为了能够让大家掌握在JBuilder4下开发分布式的多层应用系统的简单.快速的方法,达到举一反三的效果.          正文: 一步一步用JBuilder4开发EJB 一. 简介 Enterprise Java Beans(EJB)

深入理解Java内存模型系列篇

[本文转载于深入理解Java内存模型,可点击每个章节标题查看原文] 深入理解Java内存模型(一)--基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程之间没有公共状态,线程之间必

深入理解Java 对象和类_java

Java作为一种面向对象语言.支持以下基本概念: •多态 •继承 •封装 •抽象 •类 •对象 •实例 •方法 •消息解析 本节我们重点研究对象和类的概念. •对象:对象是类的一个实例,有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种:行为有:摇尾巴.叫.吃等. •类:类是一个模板,它描述一类对象的行为和状态. Java中的对象 现在让我们深入了解什么是对象.看看周围真实的世界,会发现身边有很多对象,车,狗,人等等.所有这些对象都有自己的状态和行为. 拿一条狗来举例,它的状态有

深入理解Java反射_java

要想理解反射的原理,首先要了解什么是类型信息.Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在运行时发现和使用类的信息. 1.Class对象 理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息.Class对象就是用来创建所有"常规"对象的,Java使用Class对象来执行RTTI,即使你正在执行的是类似

深入理解Java中的HashMap的实现机制_java

如果任何人让我描述一下HashMap的工作机制的话,我就简单的回答:"基于Hash的规则".这句话非常简单,但是要理解这句话之前,首先我们得了解什么是哈希,不是么? 什么是哈希 哈希简单的说就是对变量/对象的属性应用某种算法后得到的一个唯一的串,用这个串来确定变量/对象的唯一性.一个正确的哈希函数必须遵守这个准则. 当哈希函数应用在相同的对象或者equal的对象的时候,每次执行都应该返回相同的值.换句话说,两个相等的对象应该有相同的hashcode. 注:所有Java对象都从Objec

十分钟理解Java中的动态代理_java

若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述1. 什么是代理我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托者"对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就相当

一步一步搭建11gR2 rac+dg之安装rac出现问题解决(六)

一步一步在RHEL6.5+VMware Workstation 10上搭建 oracle 11gR2 rac + dg 之安装rac出现的问题 (六)   本章主要是搜集了一些安装rac的过程中出现的问题及解决办法,如果没有出现问题的话那么这一章可以不看的       目录结构: crs安装出现的问题 Oracle 11g RAC CRS-4535/ORA-15077 新安装了Oracle 11g rac之后,不知道是什么原因导致第二个节点上的crsd无法启动?其错误消息是CRS-4535: C

教你(新手)一步一步开始SEO

如果你从事SEO工作已经有段时间了,你可能对如何来优化一个网页有种直觉.你可能是同时来做好几件事,而不是执行一步一步的过程.但是如果你是正在学习SEO,或者是试图去理解SEO们是怎么来做你的网页的,那就显得有些难度了,尤其当你第一次接触这个的时候.  这篇文章旨在帮助SEO初学者们更多的了解SEO的过程,同时也帮助SEO老将们更好地与他们的客户沟通交流.我在论坛上发现很多的新手要求一步一步的SEO过程的指导.所以我就来举个以前做过的一个客户例子,一步步的解释SEO的过程 一.开始服务的第一件事是