经典软件架构模式(三)

REST模式

让我们回到服务器端开发。一直以来,互联网服务就以数据互通为最重要的业务特性。我们来看看一个微博系统的案例。

【此案例并非完全真实情况,有一定提炼修改成分】

微博作为一个非常常用的“用户制造内容”服务,一直都是各种互联网网站最喜欢的项目之一。微博本身的功能抽象并不复杂:发微博、读微博、发评论、看评论。但是需要微博数据的外部系统却很多,比如微博自己就有WEB平台、手机平台、Pad平台,在各种合作厂商那里,又要提供可以发微博晒产品、真人秀、炫耀成就……等等。可以说微博是一个结合大量其他应用系统的信息中心。初期的产品设计,可能会比较简单:

在这个模型里面,我们一般把功能分层两组,一组是本系统的服务器,如WEB平台和手机平台。另外一组是开放给第三方的接口服务器。我们希望这样能分流负载,并且隔离不同平台的故障。但是,随着业务的发展,策划有可能对最简单的微博功能,要求增加一下活动,比如“集赞抽奖”之类的,那么我们就要增加一些专门的“游戏活动”服务器。但是为了让第三方也能参加,自然就要部署多套,而且其中功能可能还有一些不同。——这就造成了积累下来的业务逻辑重复代码增多的问题。

随着第三方的接入商越来越多,除了会剧烈增加第三方TCP接口服务器的负载外,还有针对外部厂商的开发语言提供越来越多格式的API,这些维护工作量往往会占据掉开发团队大量的开发时间。有没有一种一蹴而就的方法呢?答案是有的。在互联网数据共享和互联的服务里面,一种叫REST的模型迅速超越了古老的corba RPC方案,战胜了JAVA专用的RMI技术,也干掉了各种WebService方案(包括SOAP),登上了最流行互联网接口的宝座。因此当我们改成使用REST模型的方案后,我们终于可以集中精力在微博系统本身的业务功能开发上了。

由于我们把微博的功能都集中到REST功能服务器上,我们可以把各种用户界面相关的代码独立出去,集中精力做好核心功能逻辑。同时由于所有的请求都集中到REST服务器上,在此的负载均衡和故障维护都变得统一。也无需维护多份相关的逻辑代码了。由于REST是一种跨语言的标准协议(基于HTTP),所以各种语言都有开源的REST API,这样就无需另外开发很多语言的API。为了提高外部业务的性能,还可以专门构造一个缓存系统,减少对主题功能服务器的压力。

REST模式是在Roy Thomas Fielding于2000年的博士论文提出。这篇论文的名字叫《架构风格与基于网络的软件架构设计》,在论文中,作者详细的回顾了架构模式的发展例程,并且以互联网服务为案例,逐步推演出REST架构模式,论证了其合理性和必然性。这篇论文本身就是一片对于架构模式的很好的说明(当然包括了本文前面介绍的几种模式),并且在互联网的环境下,提出了新的解决方案。这个模式的出现,说明了软件架构模式并非一层不变,而是在持续发展中的新兴科学。

“最通用的接口”——最常用于互联网公共接口 。现在的主要实现方案,一般使用HTTP协议和URI标准。

l 适应:资源型公开服务。一般互联网服务都可以抽象成“对一个由URI指定的资源”进行“增删查改”操作的模型。这种模式和按照REST定义的HTTP命令字天衣无缝的结合在一起。并且这些“资源”还可以利用缓存,来提高其性能。

l 不适应:大量临时状态服务。由于REST模式规定了“资源”必须是无状态的、可缓存的,否则就会造成大量的性能问题。因为我们如果以HTTP协议去实现这个模式,短连接和大量文本协议字的解析,在没有缓存支持下运行,将会很消耗服务器性能。况且,资源状态变化过于频繁,必定造成接口调用的频繁,这也会消耗大量网络连接。

l 方法论:以业务资源为核心设计。我们需要把我们的业务功能,抽象成可以用“资源”描述的模型,才能很好的使用REST模式。而不是简单的把URI作为某种类似“命令字”的方式来使用,那是一般的Web Service。一般我们可以把本服务的核心数据,作为“资源”来描述,然后围绕这些不同种类的资源来设计接口。以微博服务为例,微博文和评论就是这种“资源”。

l 设计模式实现:

l 命令模式:一般来说我们会把一次REST调用,看成是一个命令。而REST一共有四种命令:PUT/DELETE/GET/POST,我们只需要扩展这四个基本“命令”类型,就能很方便的实现REST模式了。

SOA模式

现代互联网服务,往往都是服务器集群来支撑的。单纯的在一个进程、一个服务器内的架构,往往不能满足需求。那么针对海量服务的服务器集群,有什么样的架构模式是可以参考的呢?我们可以来看一个案例。

假设我们要做一个电子商务的系统,这个系统无疑需要展示商品、提供购买流程。同时这个系统也需要有针对供应商的订货、发货、入账等流程。除了交易处理,还需要有评价系统管理信用;统计和推荐系统增加销售量;用户帐号系统保障安全和便利等等。这些模块和功能一般比较复杂,但是一般涉及到买家和卖家两个角色,因此我们往往根据这个规则,划定了两类模块,分别实施其功能,最后通过一个数据平台来存储这些数据。

这样的系统什么看起来问题不大,但是有两个潜在的问题:

  1. 不能应对复杂的需求变化。比如需要在同样的数据上重新开一个网店,但是仅仅售卖其中一部分货品。这就可能需要拷贝代码或者复杂的代码重构工作。如果需要增加一些促销活动,可能会涉及大量代码的修改。
  2. 不能应对自动容灾和伸缩的需求。由于用户访问量可能很大,因此我们往往需要准备大量的服务器来运行这个网站。当访问量变化的时候,没有预定的架构设计,可能会被用户量的增加打个措手不及;又或者当服务器出现故障的时候,明明有可以分担任务的服务器,但是用不上,白白给用户造成故障体验。

为了解决这两个问题,我们经过一番设计,能比较好的解决。其中最简单的是还是利用前文提到的“分层模式”,把业务分解成“顶层:面对用户的流程处理”和“底层:面对业务的系统能力”两个层面。这样的分层能让复杂的需求变化大部分集中于“顶层”部分,由于可以重用“底层”的能力,这种需求变化仅仅需要编写变化相关的代码,大大减轻了开发的工作量。然后,为了解决集群系统的性能和稳定性问题,我们把顶层到底层的调用,改成:“先通过一个【中心节点】查询,再具体调用”的方式。这样我们只要把运行状态同步到中心节点上,就能实现自动的容灾和伸缩。最后我们再启用分布式的数据存储,解决最底层数据的安全性问题。

这样的模型,实际上就是SOA模式。这种模式最大的特点,是关注服务模块之间的调用:在运行期根据负载、路由策略等用户设定,来决定模块间的调用关系。这比起以前单服务器中的观察者模式,是一种升级——让多台服务器和多个进程之间,可以在运行时协作。这种模式可以很好的实施集群的负载均衡和容灾策略。对于复杂的服务期间通信问题,也通过规定的交互接口和交互流程实现了高度的简化。很多SOA模式采用RPC框架实现,跨服务器调用往往和调用本地函数一样方便。

SOA模型的标准内容,包括一个核心服务代理模块、一批服务消费者模块、一批服务提供者模块。当然消费者本身也可以提供者。这些模块都可以是集群中的分布在不同服务器上的进程。而服务提供者通过一种叫“服务合同”的接口定义数据,来发布自己提供的服务;消费者则使用这个接口定义,发起对服务的调用,从而屏蔽底层服务交互的细节。

在集群启动后,服务提供者先发布自己的服务信息到服务代码模块进程上。服务消费者在需要时,对服务代理查找所需服务,得到能提供服务的地址、接口等信息,直接对服务提供者发起服务请求。

在以Web Service框架实现的时候,一般“服务合同”由WSDL提供,具体的服务都是Web Service,具体的编码格式有一些使用SOAP格式。 WSDL可以生成各Service Broker在实践中往往提供了负载均衡、容灾扩容等运营功能。 通常“服务代理”由一个目录服务器充当,而SOAP协议则可以直接序列化、反序列化为对象。

“云模式”——分布式业务系统。SOA是提供云服务最好的模式之一,因为云服务对于容灾和伸缩性有较高的要求,并且也需要考虑后续功能开发的便利性。

l 适应:异种系统集成。在多个不同的业务系统需要“集成”或者数据共享时,SOA模式提供了很好的伸缩性、容灾模型,以及简便的接口集成方案。

l 不适应:实时系统。由于SOA模式存在一个“查询-调用”的过程,如果对于程序响应要求很高,则不适合增加这样一个复杂的模型。SOA模式可以提供几乎无限的吞吐量,但是对于降低响应延迟却有死穴。虽然我们常常利用“缓存”中心节点数据的方式来减少服务延迟,但这也同样要付出服务器提供者状态不同步,导致请求失败的风险。

l 方法论:抽象业务逻辑为“服务”。由于SOA的核心是面对服务的,所以我们在分布式系统中,传统的面向“命令字”的思维需要扭转过来:服务是有自己的名字,规定的接口形式和固定的返回值类型的,而命令字则只有自己的类型和数据;服务是以请求-应答为标准模型的,而命令处理则只有“发送-处理”。从灵活性上来说,命令字会更好,但是从代码的可理解度来说,无疑抽象成“服务”更容易被阅读。

l 设计模式实现:

l 命令模式——尽管我们把功能抽象成服务,但是其底层实现,还是一个个的命令字往返收发实现的。使用命令模式可以很好的封装服务的底层实现。

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2015-12-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏自动化测试

DIY自动化测试【智能音箱】

    笔者从事智能音箱系统测试,这是一款基于android系统的智能语音助手产品。基本功能特性和测试方法都已稳定,目前多产品快速迭代,涉及的场景较多且数据量大...

3493
来自专栏Linyb极客之路

面对峰值响应冲击,解决高并发的三大策略

在写这篇博客的前2天,听说某系统在25人的用户量下就宕机了,实在让人震惊,所以捋了下互联网交易系统我们可以采取哪些技术来解决互联网平台下大数据量高并发的问题。

923
来自专栏编程

大型分布式服务器架构原理解析

作为技术人员,我们都知道:几乎所有的项目,都是由简单到复杂,从单一服务器到集群服务器进行开发。但又有多少人知道这其中的技术原理呢?其实,这并不是那么深奥难懂。那...

2289
来自专栏Android开发实战

腾讯最热门30款开源项目

开源是个好东西,马化腾除了王者荣耀还是干了些好事情的。腾讯最近开源的一些比较热门的项目,可以学习了解下哈

983
来自专栏Golang语言社区

再谈游戏服务器架构

一、服务器划分原则 在现有的网络游戏服务器端架构中,多是以功能和场景来划分服务器结构的。负载均衡和集群暂且不在本文中讨论(bigworld、atlas...

38313
来自专栏云计算D1net

六款不容错过的开源持续集成工具

持续集成是敏捷软件开发工作当中的一大组成部分。从一轮冲刺到下一轮冲刺,技术团队在“不断前进”的同时持续推出各类增量化功能。不过当开发人员高度专注于添加功能的同时...

3067
来自专栏编程

Android程序员的救赎之路(二)

上回说到要举一个例子来说明,在看例子前,我们先来说说问题,有时我们会在工作中遇到很难的专业问题,如设计一个业务算法或用OpenGL做3D特效,这类的问题虽然不简...

1848
来自专栏CSDN技术头条

走进 MIP,了解你不知道的移动 Web

从万维网(Web,以下简称 Web)成立,距今已经 29 年了。在 PC 时代,可以说 Web 统治了整个移动互联网,但进入移动时代后,随着 Native Ap...

702
来自专栏IT大咖说

所见即所得-基于Node.js的页面数据实践

摘要 数据抓取是企业信息化的根基和第一步,只有利用先进的技术作好了信息抓取工作,才能为信息化带来最大的价值。懂球帝高级开发工程师邓佳龙用五个字就概括了数据抓取的...

32611
来自专栏HBStream流媒体与音视频技术

DXGI快速截屏桌面直播技术

  很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等。在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引...

3396

扫码关注云+社区