人们为什么要使用REST API而不是DBAL?


32

在过去的两家公司中,我曾经使用过REST API,用于通过Web应用程序查询数据。即。而不是让Web应用程序直接执行SQL,而是调用REST API,然后执行SQL并返回结果。

我的问题是...为什么要这样做?

如果它要暴露给第三方,我可以理解。比完整的数据库更好地公开有限的REST API。但是在这两家公司中并非如此。

有人向我建议,这些REST API使在DBMS之间进行切换更加容易。但这不是数据库抽象层(DBAL)的重点吗?也许您将ORM用作DBAL,或者您可能只编写原始SQL并让DBAL在适当的情况下转换特定于DB的内容(例如,将MySQL的LIMIT转换为MSSQL的TOP)。

无论哪种方式,对我来说似乎都是不必要的。而且我认为这也使诊断问题变得更加困难。如果Web应用程序上的报告给出了错误的数字,则您不仅可以转储SQL查询,还必须转储REST URL,然后进入用作REST API的项目,并从中提取SQL。因此,这是一个额外的间接层,减慢了诊断过程。


3
听起来您只使用了基本上是CRUD的应用程序-有些用户使用表单输入数据,而另一些用户使用相同的表单或报表打印输出读取数据?如果您从未使用过需要复杂和复杂域模型的系统,那么我将了解您如何拥有特定的心态。许多应用程序需要额外的间接层来完成工作。
RibaldEddie

1
我使用的API(不一定是REST)(除其他外)对传递给它的参数执行计算。也许在这些计算中使用了DBMS,但大概很多逻辑都没有包含在DB中。但是,我工作过的公司的内部API并没有这样做。他们只是查询DBMS并逐字吐出SQL查询的结果。在我看来,REST API经常(不总是-经常)被写成时髦的,而不是实用的。
Neubert 2015年

1
REST API设计肯定存在一些怪癖,这使得很难很好地设计复杂的域-多年来我遇到的大多数开发人员都不在乎设计。他们希望尽快编写代码,以便老板喜欢他们并认为他们是摇滚明星。当您将这一事实与REST之类的趋势结合在一起时,您将获得时髦但不切实际的意大利面条API。它与REST本身无关。
RibaldEddie

3
有没有想过一些网络公司如何报告其整个用户记录被黑客窃取?有没有想过黑客是怎么做到的?当您认为Web服务器与数据库具有直接连接时,您会意识到,一旦Web服务器被黑客攻击,攻击者就拥有完全和不受限制的访问权限,可以从他喜欢的DB中选择任何内容。将其放在中间层后面,攻击者只能在中间层上调用方法。我不会说那是即时安全性,但是它明显更好。
gbjbaanb 2015年

1
@gbjbaanb:我的意思是,Web服务器可以通过其余服务器访问数据,因此,如果Web服务器被黑客攻击,攻击者还可以通过其余服务器访问数据,而不必入侵其他服务器。
JacquesB '16

Answers:


28

如果您允许客户端直接访问数据库(即使具有数据库抽象层,他们也会这样做),则:

  • 您会在他们的代码和您的代码之间取得联系-特别是,您的数据库结构和他们的代码之间存在非常牢固的联系;
  • 您的客户端可能会在数据库上做一些非常令人讨厌的事情-是否正在更新他们不应该更新的数据,编写需要花费大量时间的查询,由于无法干净地获取锁而使某些内容死锁...
  • 如果您在数据库结构中做出的选择不是最佳选择,那么很难摆脱这种选择,尤其是如果您没有使客户迁移到新结构的好方法时。

也就是说,我完全没有涉及REST部分-如果维护数据库的团队和使用该数据库的团队不同步,则在API后面隔离数据库只是一个更明智的选择,因为它允许这些部分以自己的步调发展。


24

没错,在Web应用程序和数据库之间引入REST API层并没有明显的好处,并且在复杂性和性能开销方面付出了代价。

您得到矛盾答案的原因是您对体系结构中的“客户端”感到困惑。

在您的体系结构中(如果我理解正确的话),您将使浏览器与单个Web应用程序进行交互,而Web应用程序又与数据库进行交互。在Web应用程序和数据库之间引入REST API层没有任何好处。所有陈述的好处(缓存,数据库隔离等)都可以通过代码中的数据访问层来实现。

但是还有其他一些架构,REST API是有意义的:

  • 如果您有多个客户端访问数据库-也就是说,不是单个Web应用程序而是多个独立的Web应用程序访问同一数据库。创建通用的REST接口以允许共享数据模型,缓存等可能会有所益处。当然,您可以通过共享相同的DAL库来获得一些好处,但是如果应用程序是用不同的语言和不同的方式开发的,那将是行不通的平台。这在企业系统中很常见。

  • 如果您有多个桌面应用程序直接访问数据库。这是经典的“两层”体系结构,与Web应用程序相比,它们已不受欢迎。引入REST层可以使您集中化数据访问逻辑,尤其是可以更严格地控​​制安全性,因为让多个分布式客户端直接访问同一数据库是有风险的。

  • 如果您具有直接从服务器获取数据的JavaScript代码,则无论如何都需要类似REST API的东西。


1
我喜欢您的回答,但随之而来的是其他几个查询。就像引入另一层抽象会导致性能损失一样吗?另外,难道不是使它成为单点故障(如果失败了,其他一切都崩溃了)和可能的瓶颈(每个应用程序正在等待来自池的数据库连接)吗?
sactiw

@satich:我不太清楚您要问什么,您能说得更具体些吗?您是否在询问具有或不具有REST层的单点故障?
JacquesB '16

如果您有多个与之通信的应用程序,则可以使用额外的层
Ewan

@Ewan:是的,这就是我在第一个要点指出的内容。
JacquesB

1
@JacquesB假设多个Web应用程序共享同一个数据库,但不共享相同的数据,即每个Web应用程序在该DB中对一组单独的数据进行CRUD操作,则基本上没有真正意义上的数据共享。那么,将应用程序置于Restful持久性框架之后是否有意义(还假设DB在查询中提供了良好的并发级别)?而且,对于这么多通过它进行交互的Web应用程序,该框架是否会成为瓶颈以及单点故障?
sactiw

12

警告:大文章,一些意见,含糊不清的“做对您最有效的”结论

通常,这是在数据库周围实现“六边形体系结构”的一种方式。您可以让Web应用程序,移动应用程序,桌面应用程序,批量导入器和后台处理都以统一的方式消耗您的数据库。当然,您可以通过编写用于访问数据库的丰富库并让所有进程使用该库来在某种程度上完成同一件事。实际上,如果您在一家拥有非常简单系统的小商店中,那实际上可能是一条更好的选择。这是一种更简单的方法,如果您不需要更复杂的系统的高级功能,为什么还要为此付出代价呢?但是,如果您使用的是大型,复杂的系统集,而这些系统都需要与数据库进行大规模交互,那么

平台独立性和维护

如果您有一个数据库,并且编写了一个Python库与该数据库进行交互,并且每个人都拉入该库与数据库进行交互,那就太好了。但是,突然说您需要编写一个移动应用程序,并且该移动应用程序现在还需要与数据库进行对话。而且您的iOS工程师不使用Python,而您的Android工程师也不使用Python。也许iOS人士想使用Apple的语言,而Android工程师想使用Java。然后,您将不得不使用3种不同的语言来编写和维护数据访问库。也许iOS和Android开发人员决定使用Xamarin之类的东西来最大化他们可以共享的代码。完美,除非您可能仍然需要将数据访问库移植到.NET。然后您的公司刚刚购买了另一家 的Web应用程序是一个完全不同但相关的产品,该公司希望将您公司平台中的某些数据集成到新收购的子公司的平台中。只有一个问题:附属公司是一家初创公司,决定将其大部分应用程序用Dart编写。另外,由于各种原因(原因可能超出您的控制范围),正在试用Xamarin的移动团队认为这不是针对他们的,他们宁愿使用特定于他们将要开发的移动设备的工具和语言。但是当您处于该阶段时,您的团队已经在.NET中交付了很大一部分数据访问库,并且公司中的另一个团队正在编写一些疯狂的Salesforce集成资料,并决定从那时起在.NET中进行所有这些工作。已经是的数据访问库。

因此,现在,由于发生的事件非常现实,您拥有了用Python,.NET,Swift,Java和Dart编写的数据访问库。它们也不如您希望的那样好。您无法像您想要的那样有效地使用ORM,因为每种语言都有不同的ORM工具,因此您必须编写比自己想要的更多的代码。而且,您无法为每个化身投入足够的时间,因为其中有5个。Dart版本的库特别繁琐,因为您不得不自己动手购买一些事务,因为库和支持还不存在。因此,您试图证明Dart应用程序应该只对数据库具有只读功能,但是企业已经下定决心,无论他们计划使用什么功能,都值得付出额外的努力。事实证明,数据访问库的所有这些化身中都存在一些验证逻辑中的错误。现在,您必须编写测试和代码来修复所有这些库中的此错误,获取对所有这些库所做的更改的代码审查,对所有这些库进行质量检查,并使用所有这些库。同时,您的客户不满意并进入Twitter,将您从未想到的粗俗结合在一起,更不用说针对您公司的旗舰产品了。产品负责人决定完全不了解这种情况。

请理解,在某些环境中,以上示例并非人为设计。还应考虑到这种事件序列可能会在几年的过程中发生。通常,当您到达架构师和业务人员开始谈论将其他系统连接到数据库时,就是在您想要将“将REST API放在数据库前面”纳入路线图的时候。考虑一下是否很早,当很明显该数据库将开始由几个系统共享时,在它前面放置了一个Web服务/ REST API。修复验证错误会更快,更轻松,因为您只需执行一次即可,而不是执行5次。而且发布修复程序会容易得多,因为

TLDR;与将数据访问逻辑分发到需要访问数据的每个应用程序相比,集中数据访问逻辑和维护非常瘦的HTTP客户端要容易得多。实际上,您的HTTP客户端甚至可以从元数据生成。在大型系统中,REST API可让您维护更少的代码

性能和可扩展性

有些人可能认为直接与数据库对话而不是先通过Web服务对话会更快。如果只有一个应用程序,那肯定是正确的。但是在较大的系统中,我不同意这种观点。最终,在某种程度上,将某种类型的缓存放置在数据库的前面将是非常有益的。也许您正在使用Hibernate,并且想要安装Infinispan网格作为L2缓存。如果您有4个强大的服务器集群来独立于应用程序托管Web服务,则可以负担得起具有启用同步复制的嵌入式拓扑的能力。如果您尝试将其放置在30个应用程序服务器的群集上,则在该设置中启用复制的开销会太大,因此,必须以分布式模式或某种专用拓扑来运行Infinispan,突然之间,Hibernate必须通过网络出去才能从缓存中读取。另外,Infinispan仅适用于Java。如果您使用其他语言,则需要其他缓存解决方案。在使用数据库之前,必须先从应用程序转到Web服务的网络开销很快就被需要使用更为复杂的缓存解决方案所抵消,而这些缓存解决方案通常会自身带来开销。

此外,REST API的HTTP层提供了另一种有价值的缓存机制。用于REST API的服务器可以在其响应上放置缓存头,并且这些响应可以缓存在网络层,扩展性非常好。在具有一台或两台服务器的小型设置中,最好的选择是在与数据库进行通信时仅在应用程序中使用内存中的高速缓存,但是在具有许多应用程序在许多服务器上运行的大型平台中,您希望利用网络来处理您的缓存,因为在正确配置后,诸如鱿鱼,清漆或nginx之类的东西可以在相对较小的硬件上扩展到疯狂的水平。每秒从HTTP缓存执行数十万或数百万个请求的吞吐量要比从应用程序服务器或数据库执行的便宜得多。

最重要的是,让大量的客户端全部指向您的数据库,而不是让它们全部都指向几个服务器(这些服务器又指向数据库),可能会使数据库调整和连接池的设置变得更加困难。通常,应用程序服务器上的大部分实际工作量是应用程序填充。等待数据从数据库返回通常很耗时,但通常在计算上不是很昂贵。您可能需要40台服务器来处理应用程序的工作负载,但是您可能不需要40台服务器来协调从数据库中获取数据。如果您将该任务专用于Web服务,则该Web服务可能将在运行于服务器上的服务器数量少于应用程序其余部分的服务器上,这意味着与数据库的连接数量将大大减少。这很重要,因为数据库通常不

TLDR;在单个专用Web服务中发生的事情比在使用不同语言和技术的许多不同应用程序中发生的事情更容易调整,扩展和缓存数据访问

最后的想法

请不要回避“哦,我应该一直使用REST API来获取我的数据”“这个白痴试图说我们做错了,因为我们的Web应用程序直接与数据库进行对话,”我们的东西很好!” 。我要说明的重点是,不同的系统和不同的业务有不同的要求。在很多情况下,在数据库前放置REST API确实没有任何意义。这是一个更复杂的体系结构,需要证明这种复杂性。但是,当需要保证复杂性时,使用REST API会带来很多好处。能够权衡各种问题并为您的系统选择正确的方法才是一名优秀的工程师。

此外,如果REST API妨碍了调试的方式,则该图片中可能存在某些错误或缺失。我不认为在本质上增加抽象层会增加调试的难度。当我使用大型n层系统时,我想确保拥有分布式日志记录上下文。也许当用户发起一个请求时,为该请求生成一个GUID并记录该用户的用户名和他们提出的请求。然后,当您的应用程序与其他系统对话时,将该GUID传递给它。通过适当的日志聚合和索引编制,您可以查询整个平台,以供用户报告问题,并可以查看其所有操作,并且可以遍历系统以快速确定问题出在哪里。同样,它是一个更复杂的架构,

来源:http//alistair.cockburn.us/Hexagonal+architecture https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing


很好的答案,值得一读。感谢您抽出宝贵的时间来写这个好答复!
多米尼克'18

6

如果我正确理解什么是DBAL,那么答案是REST接口允许您为其客户端使用任何语言,而DBAL是允许您为其客户端使用一种语言的库。

反过来,这对于拥有许多开发团队且并非所有开发团队都精通同一语言的公司来说可能是一个优势。允许他们的软件直接查询数据库在功能上是等效的,但是正如您所说的“比完整的数据库更好地公开有限的REST API”。

用更抽象的术语来说,您自己正在回答这个问题:

因此,这是一个额外的间接层,减慢了诊断过程

……因为有这样一种著名的格言:“计算机科学中的所有问题都可以通过间接的另一个层次来解决”。:)


6

仅仅因为您在同一家公司内,并不意味着您应该将所有东西都暴露给所有人。REST API是一种通过明确的合同来定义公司团队之间有限的消费者/提供者关系的方法。亚马逊一直是这种组织形式的先驱

API还提供了一个抽象层,使您可以使用一组特定的习惯用法-您不一定要用与数据库中使用的相同的术语与使用者进行对话。您也不一定要以相同的方式与每个消费者交谈。


3

您以为REST适用于数据库查询,而不适用于数据库查询。REST代表当前事物的状态。使用REST更改或检索表示形式,仅此而已。如果该状态可由数据库使用,则没关系,也没有人在乎,因为该表示形式如何不是REST的一部分,数据库查询也不是。


我不建议数据库查询== REST。毫无疑问,REST不仅具有数据库抽象层的功能,而且在过去我从事过的两家公司实质上就是它的全部-数据库抽象层。除了将HTTP请求转换为数据库查询外,它没有做任何其他事情。而且,如果这就是您正在做的所有事情,那么对我来说,DBAL将为您提供更好的服务。的确,在我看来,如今有些人使用REST的唯一原因是因为它很时髦-并不是因为它是解决当前任务的最佳解决方案。
Neubert 2015年

@neubert DBAL是否像REST一样直接通过Internet工作?

当然。您可以告诉MySQL使用Internet上另一台计算机的IP地址/域名/端口。您也可以使用SSH隧道以及(我相信)SSL身份验证。大概其他DBMS的工作与此类似。
Neubert 2015年

@neubert:在这种情况下,REST API DBAL,不是吗?
RemcoGerlich

2
@RemcoGerlich-可以,但是使用REST API作为您的DBAL可能会添加不必要的中间层,从而阻碍了问题的诊断。我的意思是,如果您要使用足够广泛的DBAL定义,则可以将Google SERP视为DBAL。您只需要解析HTML即可从Google的服务器中获取分页数据…
neubert
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.