十年互联网架构师,带大家深入学习常见分布式系统架构,涨薪必备

常见分布式系统架构

复杂的大型软件系统,倾向于使用分布式系统架构。就像Warren Buffett有个关于投资的名言,就是“不要把鸡蛋放在一个篮子里”。对于系统而言也是如此。厂商的机器不可能保证永远不坏,也无法保证黑客不会来对系统搞破坏,最为关键的是,我们无法保证自己的程序不会出现Bug。问题无法避免,错误也不可避免。我们只能把鸡蛋分散到不同的篮子里,来减少“一锅端”的风险。

这就是需要分布式系统的一个重要原因。

使用分布式系统的另外-一个理由是可扩展性。毕竟任何主机(哪怕是小型机、超级计算机)都会有性能的极限。而分布式系统可以通过不断扩张主机的数量以实现横向水平性能的扩展。

分布式对象体系

在基于对象的分布式系统中,对象的概念在分布式实现中起着极其关键的作用。从原理上来讲,所有的一切都被作为对象抽象出来,而客户端将以调用对象的方式来获得服务和资源。

分布式对象之所以成为重要的范型,是因为它相对比较容易地把分布的特性隐藏在对象接口后面。此外,因为对象实际上可以是任何事务,所以它也是构建系统的强大范型。

面向对象技术于20世纪80年代开始用于开发分布式系统。同样,在达到高度分布式透明性的同时,通过远程服务器宿主独立对象的理念构成了开发新--代分布式系统的稳固的基础。

在分布式对象体系架构中,比较有代表性的技术有DCOM、CORBA及RMI。

1. DCOM ( COM+)

1992年4月,微软发布Windows3.1,包括- -种被称为OLE ( Object Linking and Embedding)的机制。这允许一个程序动态链接其他库来支持其他功能,如将一个电子表格嵌入 Word文档。OLE演变成了COM ( Component Object Model)。一个COM对象是-一个二进制文件。使用COM服务的程序来访问标准化接口的COM对象,而不是其内部结构。COM对象用全局唯- -标识符(GUID )来命名,用类的ID来识别对象的类。可以有多种方法来创建- -个 COM对象,如CoGetInstance-FromFile。COM库在系统注册表中查找相应的二进制代码(一个DLL或可执行文件)来创建对象,并给调用者返回一个接口指针.COM的着眼点是在同- -台 计算机上不同应用程序之间的通信需求。

DCOM ( Distributed Component Object Model )是COM的扩展,它支持不同的两台机器上组件间的通信,而且无论它们是运行在局域网、广域网,还是Internet上。借助DCOM的应用程序将能够进行任意空间分布。DCOM于1996年在Windows NT 4.0中引入,后来更名为COM+。由于DCOM是为了支持访问远程COM对象,需要创建一个对象的过程,此时需要提供服务器的网络名及类ID。微软提供了一些机制来实现这一点。 最透明的方式是远程计算机的名称固定在注册表(或DCOM类存储)里,与特定类ID相关联。采用这种方式之后,应用程序便不知道它正在访问一个远程对象,并且可以使用与访问本地COM对象相同的接口指针。另外,应用程序也可指定一-个机器名作为参数。

由于DCOM是COM这个组件技术的无缝升级,所以能够从现有的有关COM的知识中获益,以前在COM中开发的应用程序、组件、工具都可以移入分布式的环境中。DCOM将屏蔽底层网络协议的细节,你只需要集中精力于应用。

DCOM最大的缺点是,这是微软独家的解决办法,但在跨防火墙方面的工作做得不是很好(大多数RPC系统也有类似的问题),因为防火墙必须允许某些端口来让ORPC和DCOM通过。

2. CORBA

传统的远程过程调用的机制存在一些缺陷。 例如,如果服务器没有运行,客户端是无法连接到远程过程进行调用的。管理员必须要确保在任何客户端试图连接到服务器之前将服务器启动。如果一个新服务或接口添加到了系统,客户端是不能发现的。最后,面向对象语言期望在函数调用中体现多态性,即不同类型数据的函数的行为应该有所不同,而这点恰恰是传统的RPC所不支持的。

CORBA ( Common Object Request Broker Architecture )就是为了解决上面提到的各种问题而出现的。CORBA是由OMG组织(对象管理组织)制定的一-种标准的面向对象应用程序体系规范。

或者说CORBA体系结构是OMG为解决分布式处理环境(DCE)中,硬件和软件系统的互连而提出的一种解决方案。OMG成立于1989年,作为-一个非营利性组织,致力于开发在技术上具有先进性、在商业上具有可行性并且独立于厂商的软件互联规范,推广面向对象模型技术,增强软件的可移植性( Portability)、可重用性( Reusability )和互操作性( Interoperability)。该组织成立之初,成员包括Unisys、Sun、 Cannon、 Hewlett Packard和Philips等在业界享有声誉的软硬件厂商,目前该组织拥有800多家成员。

CORBA体系的主要内容包括以下几部分。

● 对象请求代理( Object Request Broker, ORB):负责对象在分布环境中透明地收发请求和响应,它是构建分布对象应用、在异构或同构环境下实现应用间互操作的基础。

对象服务( Object Services) :为使用和实现对象而提供的基本对象集合,这些服务应独立于应用领域。主要的CORBA服务有:名录服务(NamingService)、事件服务(EventSer-vice)、生命周期服务(Life Cycle Service)、关系服务( Relationship Service) 及事务服务( Transaction Service )等。这些服务几乎包括分布系统和面向对象系统的各个方面,每个组成部分都非常复杂。

●公共设施( Common Facilitites) :向终端用户提供一-组共享服务接口,如系统管理、组合文档和电子邮件等。

应用接口( Application Interfaces) :由销售商提供的可控制其接口的产品,相应于传统的应用层表示,处于参考模型的最高层。

● 领域接口( Domain Interfaces) :为应用领域服务而提供的接口,如OMG组织为PDM系统制定的规范。

当客户端发出请求时,ORB做了如下事情。

在客户端编组参数。

定位服务器对象。如果有必要的话,它会在服务器创建- - 个过程来处理请求。

如果服务器是远程的,就使用RPC或socket来传送请求。

在服务器上将参数解析成为服务器格式。

在服务器上组装返回值。

●如果服务器是远程的,就将返回值传回。

●在客户端对返回结果进行解析。

IDL ( Itereface Definition Language )用于指定类的名字、属性和方法。它不包含对象的实现。

IDL编译器生成代码来处理编组、解封及ORB与网络之间的交互。它会生成客户机和服务器存根。

IDL是编程语言中立的,也就是说跟具体的编程语言实现无关,支持包括C、C++、 Java、Perl、Python、Ada、 COBOL、Smalltalk、 Objective C和LISP等语言。一个示例IDL如下所示。

Module Studentobject {
Struct StudentInfo {
String name;
int id;
float gpa;
};
exception Unknown {};
interface Student
StudentInfo getinfo(in string name )
raises (unknown) ;
void putinfo(in StudentInfo data) ;
};
};

IDL数据类型包括以下几种。

● 基本类型: long、short、 string、 float等。

●构造类型: struct、 union、 枚举、序列。

●对象引用。.

●any类型:一个动态类型的值。

编程中最常见的实现方式是通过对象引用来实现请求。下面是一个使用IDL的例子。

Student st = ... //获取对象的引用
try {
StudentInfo sinfo = st.getinfo("Fred Grampp") ;
} catch (Throwable e) {
//错误处理

在CORBA规范中,没有明确说明不同厂商的中间件产品要实现所有的服务功能,并且允许厂商开发自己的服务类型。因此,不同厂商的ORB产品对CORBA服务的支持能力不同,使我们在针对待开发系统的功能进行中间件产品选择时,有更多的选择余地。

当然,CORBA也存在很多不足之处。

● 尽管有多家供应商提供CORBA产品,但是仍找不到能够单独为异种网络中的所有环境提供实现的供应商。不同的CORBA实现之间会出现缺乏互操作性的现象,从而造成一些问题。 而且,由于供应商常常会自行定义扩展,而CORBA又缺乏针对多线程环境的规范,对于像C或C++这样的语言,源码兼容性并未完全实现。

●CORBA过于复杂,要熟悉CORBA,并进行相应的设计和编程,需要很多个月来掌握,而要达到专家水平,则需要好几年。

3. Java RMI

CORBA旨在提供一组全面的服务来管理在异构环境中(不同语言、操作系统、网络)的对象。

Java在其最初只支持通过socket来实现分布式通信。1995 年,作为Java的缔造者,Sun 公司开始创建-一个Java 的扩展,称为Java RMI ( Remote Method Invocation,远程方法调用)。Java RMI允许程序员创建分布式应用程序时,可以从其他Java虚拟机( JVM )调用远程对象的方法。

一旦应用程序(客户端)引用了远程对象,就可以进行远程调用了。这是通过RMI提供的命名服务(RMI注册中心)来查找远程对象,然后接收作为返回值的引用。Java RMI在概念上类似于RPC,但能在不同地址空间支持对象调用的语义。

与大多数其他诸如CORBA的RPC系统不同,RMI 只支持基于Java来构建,但也正是这个原因,RMI 对于语言来说更加整洁,无须做额外的数据序列化工作。Java RMI的设计目标如下。

●能够适应语言、集成到语言、易于使用。

●支持无缝的远程调用对象。

支持服务器到applet的回调。

●保障 Java对象的安全环境。

●支持分布式垃圾 回收。

●支持多种传输。

分布式对象模型与本地Java对象模型的相似点如下。

引用一个对象可以作为参数传递或作为返回的结果。

●远程对象 可以投到任何使用Java语法实现的远程接口的集合上。

●内 置Java instanceof操作符可以用来测试远程对象是否支持远程接口。

不同点有以下几个方面。

●远程对象的类是 与远程接口进行交互,而不是与这些接口的实现类交互。

Non-remote 参数对于远程方法调用来说是通过复制,而不是通过引用。

●远程对象是通过引用来传递, 而不是复制实际的远程实现。

●客户端必须处理额外的异常 。

在使用RMI时,所有的远程接口都继承自java.rmi.Remote接口。例如,

public interface bankaccount extends Remote
public void deposit (float amount)
throws java. rmi. RemoteException;
public void withdraw (float amount)
throws OverdrawnException,
java. rmi. RemoteException;

注意:每个方法必须在throws里面声明java.rmi.RemoteException。只要客户端调用远程方法出现失败,这个异常就会抛出。


Java.rmi.server.RemoteObject类提供了远程对象,实现的语义包括hashCode、equals 和toString。


java.rmi.server.RemoteServer及其子类提供让对象实现远程可见。java.rmiserver.UnicastRemoteObject

类定义了客户机与服务器对象实例建立一对 一的连接。

Java RMI通过创建存根函数来工作。存根由rmic编译器生成。自Java 1.5以来,Java 支持在运行时动态生成存根类。编译器rmic会提供各种编译选项。

引导名称服务提供了用于存储对远程对象的命名引用。一个远程对象引用可以存储使用类java.mi.Naming提供的基于URL的方法。例如,

BankAccount acct = new BankAcctImpl() ;
String url = "rmi:/ /java. sun. com/ account";
//绑定url到远程对象
java. rmi . Naming .bind(url, acct) ;
//查找BankAccount对 象
acct = (BankAccount) java . rmi . Naming. lookup (url) ;

RMI的另-一个优势在于,它自带分布式垃圾回收机制。根据Java虛拟机的垃圾回收机制原理,在分布式环境下,服务器进程需要知道哪些对象不再由客户端引用,从而可以被删除(垃圾回收)。

在JVM中,Java 使用引用计数。当引用计数归零时,对象将会垃圾回收。在RMI中,Java 支持两种操作: dirty 和clean。 本地JVM定期发送一个dirty到服务器来说明该对象仍在使用。定期重发dirty的周期是由服务器租赁时间来决定的。当客户端没有需要更多的本地引用远程对象时,它发送一个clean调用给服务器。不像DCOM,服务器不需要计算每个客户机使用的对象,只是简单地做下通知。如果它租赁时间到期之前没有接收到任何dirty或clean的消息,则可以安排将对象删除。

面向服务的架构

面向服务的架构( Service Oriented Architecture, SOA )基于服务组件模型,将应用程序的不同功能单元(称为服务)通过定义良好的接口契约联系起来,接口是采用中立方式进行定义的,独立于实现服务的硬件平台、操作系统和编程语言,使构建在这样系统中的服务可以以一-种统一和通用的灵活方式进行交互。SOA组件模型具备如下特点。

●可重用:一个服务创建后能用于多个应用和业务流程。

●松耦合:服务请求者到服务提供者的绑定与服务之间应该是松耦合的。因此,服务请求者不需要知道服务提供者实现的技术细节,如程序语言、底层平台等。可执行服务的网络物理位置,只需要知道服务名与服务接口即可。服务的部署、迁移和扩容极其便利。

●明确定义的服务接口: 服务交互必须是明确定义的。SOA服务组件提供标准周知的服务接口,服务请求者根据服务名和标准服务接口获取服务。Web服务描述语言( Web Services Descrip-tion Language,WSDL) 用于描述服务请求者所要求的绑定到服务提供者的细节。WSDL不包括服务实现的任何技术细节。服务请求者不知道也不关心服务究竟是由哪种程序设计语言编写的。

●基于开放标准:当前SOA的实现形式基于开放标准,例如,公有Web Service协议,或私有开放服务标准协议。可以采用第- -代Web Service定义的SOAP、WSDL和UDDI及第二代WebService定义的WS-*实现,是指定跟Web Service 相关的标准,它们大多以“WS-" 作为名字的前缀,所以统称WS-*。比如WS- Security, WS-Reliability 和WS-ReliableMessaging等。

无状态的服务设计:服务应该是独立的、自包含的请求,在实现时它不需要获取从一一个请求到另一个请求的信息或状态。服务不应该依赖于其他服务的上下文和状态。当产生依赖时,它们可以定义成通用业务流程、函数和数据模型。

SOA既不是- -项技术,也不是-一个标准,而是一种架构风格。SOA架构独立于标准,提供了架构的蓝图。架构蓝图切开、分块和组合企业应用程序层,将组件“服务”化。SOA中的服务与业务功能相关联,但在技术上独立于业务功能的实现。

1. SOA的定义和组成

Dirk Krafzig等所著的《Enterprise SOA》一书中,对SOA做了如下定义。

SOA是-一个软件架构,包含了四个关键概念:应用程序前端、服务、服务库和服务总线,一个服务包含- -个合约、 一个或多个接口及一个实现。

其中:

●应用程序前端:业务流程的所有者;

服务:提供业务的功能,可以供应用程序前端或其他服务使用;

实现:提供业务的逻辑和数据;

●合约: 为服务客户指定功能、使用和约束;

接口:物理地公开功能;

●服务库:存储SOA中各个服务的服务合约;

服务总线:将应用程序前端和服务连在- -起。

2. SOA的角色

在SOA架构中,必须有如下重要实体角色。

服务请求者( Service Customer) :服务请求者是一个应用程序、 一个软件模块或需要一个服务的另- -个服务。 它发起对服务管理中心中的服务查询(服务寻址),通过服务寻址后,与目标服务建立通道绑定服务,调用远程服务接口功能。服务请求者根据服务接口契约来获取执行远程服务。

服务提供者(ServiceProvider):服务提供者是-一个可通过网络寻址的进程实体(托管服务进程),与部署在托管服务进程下的SOA服务组件-起实现服务功能。服务提供者自动将服务组件提供的服务名发布到服务注册中心,以便服务请求者可以发现和访问该服务。服务提供者接受和执行来自请求者的请求,通过接口提供服务。

服务管理中心(ServiceManagementCenter):服务管理中心是服务提供者与服务请求者的联系中介,提供服务提供者的服务注册管理,同时提供服务请求者的服务寻址查询。提供服务管理域中全部服务资源注册管理表,以及服务查询请求接口,允许感兴趣的服务请求者查找服务资源。

SOA体系结构中的每个实体都扮演着服务提供者、请求者和管理中心这三种角色中的某-一种(或多种)。SOA 体系结构中的操作包括以下几种。

服务注册:为了使服务可访问,需要服务提供者向服务管理中心注册服务,以使服务请求者可以发现和调用它。

服务寻址:服务请求者定位服务,方法是查询服务注册中心来找到满足其服务需求的服务资源网络地址。

●服务交互(远程服务调用):在完成服务寻址之后,服务请求者根据与目标服务提供者建立的网络通道调用服务。

3.基于Web Services的SOA

Web Services是SOA架构系统的一一个实例,在SOA架构实现中应用非常广泛。

由于互联网的兴起,Web浏览器成为占主导地位的用于访问信息的模型。现在的应用设计首要任务大多数是为用户提供通过浏览器来访问,而不是编程访问或操作数据。

网页设计关注的是内容。解析展现方面往往是烦琐的。传统RPC解决方案可以工作在互联网上,但问题是,它们通常严重依赖于动态端口分配,往往要进行额外的防火墙配置。

Web Services成为一组协议,允许服务被发布、发现,并用于技术无关的形式。即服务不应该依赖于客户的语言、操作系统或机器架构。

Web Services的实现- -般是使用Web服务器作为服务请求的管道。客户端访问该服务,首先是通过一个HTTP协议发送请求到服务器上的Web服务器。Web服务器配置识别URL的一部分路径名或文件名后缀并将请求传递给特定的浏览器插件模块。这个模块可以除去头、解析数据(如果需要),并根据需要调用其他函数或模块。对于这个实现流,一个常见的例子是浏览器对于JavaServlet的支持。HTTP 请求会被转发到JVM运行的服务端代码来执行处理。

常用的基于Web Services的SOA的实现技术有XML-RPC、SOAP、.NET Remoting等。

下面展示了SOAP消息格式的一一个简单的例子。





uuid: 093a2dal -q345- 739r -ba5d-pqff98fe8j 7d
2001-11-29T13:20: 00.000-05:00


Way Lau





New York Los Angeles 2001-12-14 late afternoon

aisle Los Angeles New York

2001-12-20

mid-morning none

其中是SOAP消息中的根节点,是SOAP消息中必需的部分。是SOAP消息中可选的部分,是指消息头。 是SOAP中必需的部分,是指消息体。

4. Java中的XML Web Services

Java RMI与远程对象进行交互,其实现需要基于Java的模型。此外,它没有使用Web Services和基于HTTP的消息传递。现在,已经出现了大量的软件来支持基于Java的Web Services。 JAX-WS(JavaAPIforXMLWebServices)就是作为WebServices消息和远程过程调用的规范。JAX-Ws的一个目标是平台互操作性。其API使用SOAP和WSDL。双方不需要Java环境。

在服务器端,按照下面的步骤进行操作来创建一个RPC端点。

定义一个接口(Java接口)。

●实现服务。

创建一个发布者,用于创建服务的实例,并发布一个服务名字。

在客户端进行如下操作。

●创建一个代理(客户端存根)。wsimport命令根据WSDL文档,创建- -个客户机存根。

● 编写一个客户端,通过代理创建远程服务的一一个实例(存根),调用它的方法。

JAX-RPC执行流程如下:

●Java客户机调用存根上的方法(代理)。

●存根调用适当的Web服务。

Web服务器被调用并指导JAX-WS框架。

●框架调用实现。

实现返回结果给该框架。

该框架将结果返回给Web服务器。

●服务器将结果发送给客 户端存根。

●客户端存根返 回信息给调用者。

RESTful风格的架构

一说到REST,大家都耳熟能详,很多人的第一反应就是它是-种前端请求后台的通信方式。

甚至有些人将REST和RPC混为一谈,认为两者都是基于HTTP的类似的东西。实际上,很少有人能详细讲述REST所提出的各个约束、风格特点及如何开始搭建REST服务。

1.什么是REST

表述性状态转移( REpresentation State Transfer, REST) 描述了一个架构样式的网络系统,比如Web应用程序。它首次出现在2000年Roy Fielding的博士论文Architectural Styles and the DesignofNetwork-based Sofware Architectures①中。Roy Fielding同时还是HTTP规范的主要编写者之一,也是Apache HTTP服务器项目的共同创立者。所以这篇文章-发表, 就引起了极大的反响。很多公司或组织如雨后春笋般宣称自己的应用或服务实现了REST API。但该论文实际上只是描述了一种架构风格,并未对具体的实现做出规范。所以社会上,各大厂商不免误用或滥用REST。所以在这种背景下,Roy Fielding不得不再次发文做了澄清。同时他还指出,除非应用状态引擎是超文本驱动的,否则它就不是REST或REST API。据此,他给出了REST API应该具备的条件。

RESTAPI不应该依赖于任何通信协议,尽管要成功映射到某个协议可能会依赖于元数据的可用性、所选的方法等。

REST API不应该包含对通信协议的任何改动,除非是补充或确定标准协议中未规定的部分。

REST API应该将大部分的描述工作放在定义用于表示资源和驱动应用状态的媒体类型上,或定义现有标准媒体类型的扩展关系名和(或)支持超文本的标记。

REST API绝不应该定义一个固定的资源名或层次结构(客户端和服务器之间的明显耦合)。

REST API永远也不应该有那些会影响客户端的“类型化”资源。

REST API不应该要求有先验知识( Prior Knowledge),除了初始URI和适合目标用户的一-组标准化的媒体类型(即它能被任何潜在使用该API的客户端理解)。

REST并非标准,而是- -种开发Web应用的架构风格,可以将其理解为一种设计模式。REST基于HTTP、URI及XML这些现有的广泛流行的协议和标准,伴随着REST的应用,HTTP协议得到了更加正确的使用。

2. REST有哪些特征

REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是REST。

相较于基于SOAP和WSDL的Web服务,REST 模式提供了更为简洁的实现方案。REST Web服务( RESTful web services )是松耦合的,这特别适用于为客户创建在互联网传播的轻量级的Web服务API。REST应用是围绕“资源表述的转移( the transfer of representations of resources)”为中心来做请求和响应。数据和功能均被视为资源,并使用统- -资源标识符(URI)来访问资源。网页里面的链接就是典型的URI。该资源由文档表述,并通过使用一组简单的、定义明确的操作来执行。

例如,一个REST资源可能是- -个城市当前的天气情况。该资源的表述可能是-个XML文档、图像文件或HTML页面。客户端可以检索资源的特定表述,也可以通过更新其数据来修改对应的资源,或者完全删除该资源。

目前,越来越多的Web服务开始采用REST风格设计和实现,真实世界中比较著名的REST服务包括: Google AJAX搜索API、Amazon Simple Storage Service ( AmazonS3 )等。

基于REST的Web服务遵循- -些基本的设计原则,使RESTful应用更加简单、轻量,开发速度也更快。

●通过URI来标识资源:系统中的每--个对象或资源都可以通过一个唯一的URI来进行寻址,URI的结构应该简单、可预测且易于理解,比如定义目录结构式的URI。

统一接口:以遵循RFC-2616所定义的协议方式显式地使用HTTP方法,建立创建、检索、更新和删除(CRUD: Create, Retrieve, Update and Delete )操作与HTTP方法之间的-一对一映射。

*若要在服务器上创建资源,应该使用POST方法。

*若要检索某个资源,应该使用GET方法。

*若要更新或添加资源,应该使用PUT方法。

*若要删除某个资源,应该使用DELETE方法。

●资源多重表述: URI所访问的每个资源都可以使用不同的形式加以表示(如XML或JSON),具体的表现形式取决于访问资源的客户端。客户端与服务提供者使用一一种内容协商的机制(请求头与MIME类型)来选择合适的数据格式,最小化彼此之间的数据耦合。

●无状态:对服务器端的请求应该是无状态的,完整、独立的请求不要求服务器在处理请求时检索任何类型的应用程序上下文或状态。无状态约束使服务器的变化对客户端是不可见的,因为在两次连续的请求中,客户端并不依赖于同一台服务器。- -个客户端从某台服务器上收到- -份包含链接的文档,当它要做一些处理时,这台服务器宕机了,可能是硬盘损坏而被拿去修理,可能是软件需要升级重启一如果这个客户端访问了从这台服务器接收的链接,它不会察觉到后台的服务器已经改变了。通过超链接实现有状态交互,即请求消息是自包含的(每次交互都包含完整的信息),有多种技术实现了不同请求间状态信息的传输,如URI重新,Cookies 和隐藏表单字段等,状态可以嵌人到应答消息里,这样-来状态在接下来的交互中仍然有效。

下面是一个HTTP请求方法在RESTful Web服务中的典型应用。

十年互联网架构师,带大家深入学习常见分布式系统架构,涨薪必备_第1张图片

3. Java REST规范

针对REST在Java中的规范,主要是JAX-RS ( Java API for RESTful Web Services)。该规范使得Java 程序员可以使用一套固定的接口来开发REST应用,避免了依赖于第三方框架。同时,JAX-RS使用POJO编程模型和基于标注的配置,并集成了JAXB,从而可以有效缩短REST应用的开发周期。Java E 6引入了对JSR-311 ( http:/p/org/n/i/e/ail?id=-311)的支持,Java EE 7支持JSR-339 ( ht:/:p:o/g/9/js/de/ai?id 39 )规范。而在最新发布的Java EE8中,则是支持了规范JSR-370 ( htt:p.org/e/j/etail?id=370)。

JAX-RS定义的API位于javax.ws.rs包中。

伴随着JSR 311规范的发布,Sun 同步发布该规范的参考实现Jersey ( ht/je/ieyijava.net)。

第三方提供JAX-RS的具体实现还包括Apache的CXF ( htp://exf.apache.orge)及JBoss 的REST-Easy ( ht:estesyijboss.or.g等。未实现该规范的其他REST框架还包括SpringMVC ( htp://spring.io)等。

本文后续内容也会对如何构建RESTful服务做详解讲解。

微服务架构及容器技术

自2014年始,微服务( Microservices)一词越来越火爆,各大技术峰会都以微服务为主题展开了热烈探讨。微服务架构( Micoservices Architecture, MSA)的诞生并非偶然,它的产生主要依赖于以下方面的内容。

领域驱动设计:指导我们如何分析并模型化复杂的业务。

敏捷方法论:帮助快速发布产品,形成有效反馈。

持续交付:促使我们构建更快、更可靠、更频繁的软件部署和交付能力。

虚拟化和基础设施自动化:特别是以Docker为代表的容器技术,帮助我们简化环境的创建和安装。

DevOps:全功能化的小团队,让开发、测试、运维有效地整合起来。

James Lewis和Martin Fowler对微服务架构做了如下定义。

简而言之,微服务架构风格就像是把小的服务开发成单- -应用的形式, 运行在其自己的进程中,并采用轻量级的机制进行通信(- -般是HTTP资源API)。这些服务都围绕业务能力来构建,通过全自动部署工具来实现独立部署。这些服务可以使用不同的编程语言和不同的数据存储技术,并保持最小化集中管理。

1. MSA特征

MSA包含如下特征。

组件以服务形式来提供:正如其名,微服务也是面向服务的。

围绕业务功能进行组织:微服务更倾向于围绕业务功能对服务结构进行划分、拆解。这样的微服务是针对特定业务领域的、有着完整实现的应用软件,它包含了使用的接口、持久存储及对外的交互。因此微服务的团队应该是跨职能的,包含完整的开发技术、用户体验、数据库及项目管理。

●产品不是项目:传统的开发模式致力于提供一 些被认为是完整的软件。一旦开发完成,软件将移交给维护或实施部门,然后开发组就可以解散了。而微服务要求开发团队对软件产品的整个生命周期负责。这要求开发者每天都关注软件产品的运行情况,并与用户联系得更紧密,同时承担一些售后支持。越小的服务粒度越容易促进用户与服务提供商之间的关系。Amazon的理念就是“You build, you runit”,这也正是DevOps的文化理念。

强化终端及弱化通道:微服务的应用致力松耦合和高内聚,它们更喜欢简单的REST风格,而不是复杂的协议(如WS、BPEL 或集中式框架)。或者采用轻量级消息总线(如RabbitMQ或ZeroMQ等)来发布消息。

分散治理:这是跟传统的集中式管理有很大区别的地方。微服务把整体式框架中的组件拆分成不同的服务,在构建它们时将会有更多的选择。

分散数据管理:当整体式的应用使用单- -逻 辑数据库对数据持久化时,企业通常选择在应用的范围内使用--个数据库。微服务让每个服务管理自己的数据库,无论是相同数据库的不同实例,或者是不同的数据库系统。

基础设施自动化:云计算,特别是AWS的发展,减少了构建、发布、运维微服务的复杂性。

微服务的团队更加依赖于基础设施的自动化,毕竟发布工作相当无趣。近些年开始火爆的容器技术,如Docker也是-一个不错的选择。( 有关容器技术及Docker的内容在后面章节会涉及)容错性设计:任务服务都可能因为供应商的不可靠而产生故障。微服务应为每个应用的服务及数据中心提供日常故障检测和恢复。

改进设计:由于设计会不断更改,微服务所提供的服务应该能够替换或报废,而不是要长久地发展的。

2. MSA与SOA的区别和联系

微服务架构(MSA)与面向服务架构(SOA)有相似之处,比如,都是面向服务,通信大多是基于HTTP协议。通常传统的SOA意味着大而全的单块架构( Monolithic Architecture)的解决方案。这让设计、开发、测试、发布都增加了难度,其中任何细小的代码变更,都将导致整个系统的需要重新测试、部署。而微服务架构恰恰把所有服务都打散,设置合理的颗粒度,各个服务间保持低耦合,每个服务都在其完整的生命周期中存活,把互相之间的影响降到最低。

SOA需要对整个系统进行规范,而MSA每个服务都可以有自己的开发语言和开发方式,灵活性大大提高。

SOA这个方案的好处有以下几个方面。

易于开发:当前开发工具和IDE的目标就是支持这种单块应用的开发。

易于部署:你只需要将WAR文件或目录结构放到合适的运行环境下即可。

易于伸缩:你只需要在负载均衡器下面运行应用的多份拷贝就可以伸缩。

但是,一旦应用变大、团队增长,这种方法的缺点就愈加明显,主要表现在以下几个方面。

代码库庞大:巨大的单块代码库可能会吓到开发者,尤其是团队的新人。应用难于理解和修改。

因此,开发速度通常会减缓。另外,由于没有模块硬边界,模块化也随时间而破坏。另外,因为难以理解如何实现变更,代码质量也随时间下降。这是个恶性循环。

IDE超载:代码库越大,IDE 越慢,开发者效率越低。

Web容器超载:应用越大,容器启动时间越长。因此,开发者大量的时间被浪费在等待容器启动上。这也会影响到部署。

难以持续部署:对于频繁部署,巨大的单块应用也是个问题。为了更新- - 个组件,你必须重新部署整个应用。这还会中断后台任务(如Java应用的Quartz 作业),不管变更是否影响到这些任务,都有可能引发问题。未被更新的组件也可能因此而不能正常启动。因此,鉴于重新部署的相关风险会增加,不鼓励频繁更新。这尤其对用户界面的开发者来说是个问题,因为他们通常需要快速迭代,频繁重新部署。

●难以伸缩应用:单块架构只能在一-个维度伸缩。-方面,它可以通过运行多个拷贝来伸缩以满足业务量的增加,某些云服务甚至可以动态地根据负载调整应用实例的数量。但是另-方面,该架构不能伸缩满足数据量的增加。每个应用实例都要访问全部数据,这使缓存低效,并且提升了内存占用和I/0流量。而且,不同的组件所需资源不同,一些可能是CPU密集型的,另-些可能是内存密集型的。单块架构下,我们不能独立伸缩各个组件。

●难以调整开发规模: 单块应用对调整开发规模也是个障碍。一旦应用达到一定规模,将工程组织分成专注于特定功能模块的团队通常更有效。比如,我们可能需要UI团队、会计团队、库.存团队等。单块应用的问题:是它阻碍组织团队相互独立地工作。团队之间必须在开发进度和重新部署上进行协调。对团队来说,也很难改变和更新产品。

●需要对一个技术栈长期投入:单块架构迫使你采用开发初期选择的技术栈(某些情况下,是那项技术的某个版本)。并且,在单块架构下,很难递增式地采用更新的技术。比如,想象- -下你选了JVM。除了Java你还可以选择其他使用JVM的语言,如Groovy和Scala也可以与Java很好地进行互操作。但是在单块架构下,非JVM语言写的组件就不行。而且,如果应用使用了过时的平台框架,将应用迁移到更新更好的框架上就很有挑战性。为了能够将应用迁移到新的平台框架,你不得不需要重写整个应用,这就太冒险了。

微服务架构正是解决单块架构缺点的替代模式。

使用微服务架构的好处有以下几个方面。

●每个微服务都相对较小。

*易于开发者理解。

* IDE反应更快,开发者更高效。

* Web 容器启动更快,开发者更高效,并提升了部署速度。

●每个服务都可以独立部署,易于频繁部署新版本的服务。

●易于伸缩开 发组织结构。你可以对多个团队的开发工作进行组织。每个团队负责单个服务。每个团队可以独立于其他团队开发、部署和伸缩服务。

提升故障隔离。比如,如果一个服务 存在内存泄露,那么只有该服务受影响,其他服务仍然可以处理请求。相比之下,单块架构的一一个出错组件可以拖垮整个系统。

●每个服 务可以单独开发和部署。

●消除了任何对技术栈的长期投入。

这个方案也有一些缺点,主要表现在以下几个方面。

●开发者要处理分布式系统的额外复杂度。

●开发者IDE大多是面向构建单块应用的,并没有显式提供对开发分布式应用的支持。

●测试更加困难。

●开发者需要实现服务间通信机制。

●不使用分 布式事务实现跨服务的用例更加困难。

●实现跨服 务的用例需要团队间的细致协作。

生产环境的部署复杂度。对于包含多种不同服务类型的系统,部署和管理的操作复杂度仍然存在。

●内存消耗增加。微服务架构使用NxM个服务实例来替代N个单块应用实例。如果每个服务运行在自己已独立的JVM.上,通常有必要对实例进行隔离,对这么多运行的JVN,就有M倍的开销。另外,如果每个服务运行在独立的虚拟机上,那么开销会更大。

3.如何构建微服务

如何构建微服务真是一个大话题。目前,很多技术都可以实现微服务,如ZooKeeper、Dubbo、Jersey. Spring Boot、Spring Cloud 等。本书主要围绕Spring Cloud技术栈来实现一个完整的企业级微服务架构系统。

本篇内容给大家讲解的是常见分布式系统架构的内容,喜欢的朋友可以转发关注小编一波!!

 

你可能感兴趣的:(Java,程序员,编程,学习,架构,java)