por que as pessoas fazem API REST em vez de DBAL?

32

Nas duas últimas empresas que estive nas APIs REST existem para consultar dados por meio de um aplicativo Web. ie em vez de fazer com que o aplicativo Web faça o SQL diretamente, ele chama uma API REST, que executa o SQL e retorna o resultado.

Minha pergunta é ... por que isso é feito?

Se fosse exposto a terceiros eu poderia entender. Melhor expor uma API REST limitada do que o banco de dados completo. Mas nessas duas empresas não é esse o caso.

Foi-me sugerido que essas APIs REST facilitam a alternância entre DBMSs. Mas não é esse o objetivo de uma camada de abstração de banco de dados (DBAL)? Talvez você use um ORM como seu DBAL ou talvez apenas escreva SQL bruto e faça com que seu DBAL traduza o material específico do DB, se apropriado (por exemplo, traduza LIMIT para MySQL e TOP para MSSQL).

De qualquer forma, parece-me desnecessário. E acho que isso também dificulta o diagnóstico de problemas. Se um relatório no aplicativo da web está fornecendo os números errados, você não pode simplesmente despejar a consulta SQL - é necessário despejar a URL REST e depois entrar no projeto que serve como API REST e extrair o SQL. Portanto, é uma camada extra de indireção que atrasa o processo de diagnóstico.

Neubert
fonte
3
Parece que você trabalhou apenas com aplicativos basicamente CRUD - alguns usuários inserem dados com formulários e outros leem com os mesmos formulários ou com impressões de relatórios? Se você nunca trabalhou com um sistema que precisa de um modelo de domínio complexo e sofisticado, posso ver como você teria essa mentalidade específica. Muitos aplicativos exigem essa camada extra de indireção para fazer as coisas.
RibaldEddie
1
Eu trabalhei com APIs (não necessariamente REST) ​​que (entre outras coisas) executavam cálculos nos parâmetros que foram passados ​​para ele. Talvez um DBMS seja utilizado nesses cálculos, mas presumivelmente grande parte da lógica não está no DB. No entanto, as APIs internas das empresas em que trabalhei não fazem isso. Eles apenas consultam um DBMS e cospem os resultados da consulta SQL literalmente. Parece-me que as APIs REST são frequentemente (nem sempre - frequentemente) escritas para estar na moda - para não serem práticas.
Neubert 30/03
1
Definitivamente, existem peculiaridades no design da API REST que dificultam o design de um domínio complexo - a maioria dos desenvolvedores que conheci ao longo dos anos não se importa com o design. Eles querem produzir código o mais rápido possível, para que seus chefes os amem e pensem que são estrelas do rock. Ao combinar esse fato com uma tendência como REST, você obtém uma API de espaguete moderna, mas impraticável. Não tem nada a ver com o próprio REST.
RibaldEddie
3
Você já se perguntou como algumas empresas da web relatam que todos os seus registros de usuários foram roubados por um hacker? Você já se perguntou como o hacker fez isso? Quando você pensa que um servidor da Web tem uma conexão direta com o banco de dados, percebe que, uma vez hackeado, o invasor tem acesso total e irrestrito para selecionar qualquer coisa do banco de dados que ele gosta. Coloque-o atrás de uma camada intermediária e o invasor poderá chamar apenas métodos na camada intermediária. Não vou dizer que é segurança instantânea, mas é significativamente melhor.
Gbjbaanb
1
@gbjbaanb: Meu argumento é que o servidor da web pode acessar os dados através do servidor de descanso; portanto, se o servidor da web for invadido, o invasor também poderá acessar os dados através do servidor de descanso sem precisar hackear o servidor de descanso.
JacquesB

Respostas:

28

Se você permitir que um cliente acesse o banco de dados diretamente - o que faria, mesmo com uma camada de abstração do banco de dados, então:

  • Você obtém um acoplamento entre o código deles e o seu - particularmente, há um acoplamento muito forte entre a estrutura do banco de dados e o código;
  • Seu cliente pode fazer algumas coisas indesejáveis ​​em seu banco de dados - seja atualizando dados que não deveriam, escrevendo uma consulta que leva muito tempo, bloqueando algo porque eles não adquirem bloqueios de maneira limpa ...
  • Se você fez uma escolha pouco otimizada em sua estrutura de banco de dados, sair dessa opção pode ser muito difícil, especialmente se você não tiver uma boa maneira de fazer seus clientes migrarem para novas estruturas.

Ou seja, não estou tocando nada na parte REST - isolar seu banco de dados atrás de uma API é simplesmente uma escolha mais sensata se a equipe que mantém o banco de dados e as equipes que o usam não estiverem sincronizadas, pois permite que essas partes evoluir no seu próprio ritmo.

jhominal
fonte
24

Você está certo, não há benefício claro em introduzir uma camada da API REST entre um aplicativo Web e um banco de dados, e isso tem um custo em complexidade e sobrecarga de desempenho.

A razão pela qual você está obtendo respostas contraditórias é a confusão sobre o que é o 'cliente' em sua arquitetura.

Na sua arquitetura (se bem entendi), você tem navegadores interagindo com um único aplicativo Web, que por sua vez está interagindo com o banco de dados. A introdução de uma camada de API REST entre o aplicativo Web e o banco de dados não tem benefício. Todos os benefícios declarados (armazenamento em cache, isolamento do banco de dados etc.) podem ser alcançados com as camadas de acesso a dados no código.

Mas existem outras arquiteturas nas quais uma API REST faz sentido:

  • Se você tiver vários clientes acessando o banco de dados - ou seja, não um único aplicativo Web, mas vários aplicativos independentes da Web acessando o mesmo banco de dados. Pode ser vantajoso criar uma interface REST comum para permitir o compartilhamento de modelo de dados, armazenamento em cache etc. Claro que você pode obter alguns benefícios compartilhando as mesmas bibliotecas DAL, mas isso não funcionará se os aplicativos forem desenvolvidos em diferentes idiomas e em diferentes plataformas. Isso é comum em sistemas corporativos.

  • Se você tiver vários aplicativos de desktop acessando o banco de dados diretamente. Essa é a arquitetura clássica de "duas camadas", que caiu em desuso em comparação aos aplicativos da web. A introdução de uma camada REST permite centralizar a lógica de acesso a dados e, principalmente, permite um controle mais rígido da segurança, pois é arriscado ter vários clientes distribuídos acessando diretamente o mesmo banco de dados.

  • Se você possui um código JavaScript que busca diretamente dados do servidor, é necessário algo como uma API REST.

JacquesB
fonte
1
Gostei da sua resposta, mas tenho mais algumas consultas. Como e a perda de desempenho com a introdução de outra camada de abstração? Além disso, não é o único ponto de falha (se tudo der errado, tudo o resto fica inativo) e possível gargalo (cada aplicativo aguardando conexão com o banco de dados do pool)?
sactiw
@ satich: Eu não entendo exatamente o que você está perguntando, você pode ser mais específico? Você está perguntando sobre um ponto de falha único com ou sem uma camada REST?
JacquesB
A camada extra pode ter um uso se você tiver mais de um aplicativo se comunicar com ele
Ewan
@ Ewan: Sim, é isso que afirmo no primeiro ponto.
JacquesB
1
@JacquesB Suponha que vários aplicativos da Web compartilhem o mesmo banco de dados, mas não os mesmos dados, ou seja, cada um executando operações CRUD em um conjunto separado de dados dentro desse banco de dados, basicamente não há compartilhamento de dados no verdadeiro sentido. Portanto, colocar os aplicativos por trás de uma estrutura de persistência Restful faz algum sentido (também suponha que o DB forneça um bom nível de simultaneidade nas consultas)? Além disso, essa estrutura não será um gargalo e um único ponto de falha para tantos aplicativos da web interagindo por ela?
sactiw
12

Atenção: post grande, algumas opiniões, conclusão vaga 'faça o que funciona melhor para você'

Geralmente, isso é feito como um meio de implementar a 'arquitetura hexagonal' em torno do seu banco de dados. Você pode ter aplicativos da Web, aplicativos móveis, aplicativos de desktop, importadores em massa e processamento em segundo plano, consumindo seu banco de dados de maneira uniforme. Certamente você poderia realizar a mesma coisa, até certo ponto, escrevendo uma biblioteca rica para acessar seu banco de dados e fazendo com que todos os seus processos usassem essa biblioteca. E, de fato, se você estiver em uma pequena loja com um sistema muito simples, esse é provavelmente o melhor caminho a percorrer; É uma abordagem mais simples e, se você não precisa dos recursos avançados de um sistema mais complicado, por que pagar pela complexidade? No entanto, se você estiver trabalhando com um conjunto grande e sofisticado de sistemas que precisam interagir com o banco de dados em grande escala,

Independência e manutenção da plataforma

Se você tem um banco de dados e escreve uma biblioteca Python para interagir com esse banco de dados, e todo mundo puxa essa biblioteca para interagir com o banco de dados, isso é ótimo. Mas digamos que de repente você precise escrever um aplicativo móvel, e esse aplicativo móvel agora também precise conversar com o banco de dados. E seus engenheiros iOS não usam Python, e seus engenheiros Android não usam Python. Talvez o pessoal do iOS queira usar as linguagens da Apple e os engenheiros do Android queiram usar Java. Então você ficaria preso escrevendo e mantendo sua biblioteca de acesso a dados em 3 idiomas diferentes. Talvez os desenvolvedores de iOS e Android decidam usar algo como o Xamarin para maximizar o código que podem compartilhar. Perfeito, exceto que você provavelmente ainda precisará portar sua biblioteca de acesso a dados para o .NET. E então sua empresa acabou de comprar outra empresa que ' O aplicativo da web é um produto díspar, mas relacionado, e a empresa deseja integrar alguns dos dados da plataforma da sua empresa na plataforma da subsidiária recém-adquirida. Só há um problema: a subsidiária era uma start-up e decidiu escrever a maior parte de sua aplicação no Dart. Além disso, por qualquer motivo (provavelmente fora do seu controle), a equipe móvel que estava pilotando o Xamarin decidiu que não era para eles e que preferia usar as ferramentas e os idiomas específicos para os dispositivos móveis para os quais desenvolverá. Mas enquanto você estava nessa fase, sua equipe já havia entregue uma grande parte da sua biblioteca de acesso a dados no .NET, e outra equipe da empresa estava escrevendo algumas coisas malucas de integração do Salesforce e decidiu fazer tudo isso no .NET desde lá. já era uma biblioteca de acesso a dados.

Portanto, agora, devido a uma reviravolta muito realista, você tem sua biblioteca de acesso a dados escrita em Python, .NET, Swift, Java e Dart. Eles não são tão legais quanto você gostaria que fossem. Você não pode usar um ORM da maneira mais eficaz que deseja, porque cada idioma possui ferramentas ORM diferentes; portanto, você precisa escrever mais código do que gostaria. E você não foi capaz de dedicar tanto tempo a cada encarnação quanto gostaria, porque há cinco deles. E a versão Dart da biblioteca é especialmente complicada, porque você precisava criar coisas transacionais para algumas delas, porque as bibliotecas e o suporte simplesmente não estavam lá. Você tentou argumentar que, por causa disso, o aplicativo Dart deveria ter apenas a funcionalidade somente leitura do seu banco de dados, mas a empresa já havia decidido que quaisquer recursos que planejassem valiam o esforço extra. E acontece que há um erro em algumas lógicas de validação que existem em todas essas encarnações da sua biblioteca de acesso a dados. Agora você deve escrever testes e códigos para corrigir esse bug em todas essas bibliotecas, obter revisões de código para suas alterações em todas essas bibliotecas, obter controle de qualidade em todas essas bibliotecas e lançar suas alterações em todos os sistemas usando todos os essas bibliotecas. Enquanto isso, seus clientes estão descontentes e adotaram o Twitter, reunindo combinações de vulgaridades que você nunca imaginou que poderiam ser concebidas, muito menos direcionadas ao principal produto de sua empresa. E o proprietário do produto decide não ter muita compreensão da situação.

Por favor, entenda que em alguns ambientes, o exemplo acima é tudo menos artificial. Também leve em consideração que essa sequência de eventos pode se desdobrar ao longo de alguns anos. Geralmente, quando você chega ao ponto em que arquitetos e pessoas de negócios começam a falar sobre como conectar outros sistemas ao banco de dados, é nesse momento que você deseja 'colocar uma API REST na frente do banco de dados' no seu roteiro. Considere, desde o início, quando ficou claro que esse banco de dados começaria a ser compartilhado por alguns sistemas, que um serviço da web / API REST foi colocado na frente dele. Corrigir o erro de validação seria muito mais rápido e fácil, porque você está fazendo uma vez em vez de cinco vezes. E liberar a correção seria muito mais fácil de coordenar, porque você '

TLDR; É mais fácil centralizar a lógica de acesso a dados e manter clientes HTTP muito finos do que distribuir a lógica de acesso a dados para cada aplicativo que precisa acessar os dados. De fato, seu cliente HTTP pode até ser gerado a partir de metadados. Em sistemas grandes, a API REST permite manter menos código

Desempenho e escalabilidade

Algumas pessoas podem acreditar que conversar com o banco de dados diretamente, em vez de passar primeiro por um serviço da web, é mais rápido. Se você tem apenas um aplicativo, isso certamente é verdade. Mas em sistemas maiores, eu discordo do sentimento. Eventualmente, em algum nível de escala, será muito benéfico colocar algum tipo de cache na frente do banco de dados. Talvez você esteja usando o Hibernate e queira instalar uma grade Infinispan como um cache L2. Se você possui um cluster de 4 servidores robustos para hospedar seu serviço da Web separado de seus aplicativos, pode se dar ao luxo de ter uma topologia incorporada com replicação síncrona ativada. Se você tentar colocar isso em um cluster de 30 servidores de aplicativos, a sobrecarga de ativar a replicação nessa configuração será muito grande; É necessário executar o Infinispan em um modo distribuído ou em algum tipo de topologia dedicada, e de repente o Hibernate precisa sair pela rede para ler a partir do cache. Além disso, o Infinispan funciona apenas em Java. Se você tiver outros idiomas, precisará de outras soluções de cache. A sobrecarga de rede de ter que passar do aplicativo para o serviço da web antes de chegar ao banco de dados é rapidamente compensada pela necessidade de usar soluções de cache muito mais complicadas que geralmente vêm com sobrecarga própria.

Além disso, essa camada HTTP da API REST fornece outro mecanismo valioso de armazenamento em cache. Seus servidores para sua API REST podem colocar cabeçalhos de cache em suas respostas, e essas respostas podem ser armazenadas em cache na camada de rede, que se adapta excepcionalmente bem. Em uma configuração pequena, com um ou dois servidores, sua melhor aposta é usar apenas um cache de memória no aplicativo quando ele se comunica com o banco de dados, mas em uma grande plataforma com muitos aplicativos em execução em vários servidores, você deseja aproveitar o rede para lidar com o armazenamento em cache, porque, quando configurado corretamente, algo como squid, verniz ou nginx pode ser expandido para níveis insanos em hardware relativamente pequeno. Centenas de milhares ou milhões de solicitações por segundo de taxa de transferência são muito mais baratas a partir de um cache HTTP do que de um servidor de aplicativos ou de um banco de dados.

Além disso, ter vários clientes apontados para o banco de dados, em vez de apontar para alguns servidores que, por sua vez, apontam para o banco de dados, pode dificultar muito o ajuste do banco de dados e do pool de conexões. Em geral, a maior parte da carga de trabalho real em um servidor de aplicativos é material de aplicativo; esperar que os dados retornem do banco de dados geralmente consome tempo, mas geralmente não é muito caro em termos computacionais. Você pode precisar de 40 servidores para lidar com a carga de trabalho do seu aplicativo, mas provavelmente não precisa de 40 servidores para orquestrar a busca dos dados no banco de dados. Se você dedicar essa tarefa a um serviço da Web, o serviço da Web provavelmente estará em execução em muito menos servidores que o restante do aplicativo, o que significa que você precisará de muito menos conexões com o banco de dados. O que é importante, porque os bancos de dados geralmente não

TLDR; É mais fácil ajustar, dimensionar e armazenar em cache o acesso aos dados quando ocorre algo dentro de um único serviço da web dedicado do que quando ocorre em vários aplicativos diferentes usando diferentes idiomas e tecnologias

Pensamentos finais

Por favor, não se afaste desse pensamento "Ah, uau, eu sempre deveria estar usando APIs REST para obter meus dados" ou "Esse idiota está tentando dizer que estamos fazendo errado, porque nosso aplicativo Web conversa diretamente com o banco de dados, mas nossas coisas funcionam bem! " . O ponto principal que estou tentando destacar é que sistemas diferentes e empresas diferentes têm requisitos diferentes; Em muitos casos, colocar uma API REST na frente do seu banco de dados realmente não faz sentido. É uma arquitetura mais complicada que requer justificação dessa complexidade. Mas quando a complexidade é justificada, há muitos benefícios em ter a API REST. Ser capaz de avaliar as diferentes preocupações e escolher a abordagem certa para o seu sistema é o que faz um bom engenheiro.

Além disso, se a API REST estiver atrapalhando a depuração, provavelmente haverá algo errado ou faltando nessa imagem. Não acredito que ter essa camada de abstração adicionada intrinsecamente torne a depuração mais difícil. Quando trabalho com sistemas grandes de n camadas, gosto de ter um contexto de log distribuído. Talvez quando um usuário inicia uma solicitação, gere um GUID para essa solicitação e registre o nome de usuário desse usuário e a solicitação que ele fez. Em seguida, passe esse GUID enquanto seu aplicativo se comunica com outros sistemas. Com agregação e indexação de log adequadas, você pode consultar toda a plataforma para o usuário que está relatando o problema e ter visibilidade de todas as suas ações, e elas passam pelo sistema para identificar rapidamente onde as coisas deram errado. Novamente, é uma arquitetura mais complicada,

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

Cães
fonte
Resposta muito boa, vale a pena ler. Obrigado por dedicar um tempo para escrever esta ótima resposta!
26618 Dominic
6

Se eu entendi corretamente o que é um DBAL , a resposta é que uma interface REST permite que você use qualquer idioma para seus clientes, enquanto um DBAL é uma biblioteca que permite usar um único idioma para seus clientes.

Por sua vez, isso pode ser uma vantagem para uma empresa onde existem muitas equipes de desenvolvimento e nem todas são proficientes no mesmo idioma. Permitir que o software consulte diretamente o banco de dados seria equivalente em funcionalidade, mas como você diz "é melhor expor uma API REST limitada do que o banco de dados completo".

Em termos mais abstratos, você mesmo está respondendo à pergunta:

Portanto, é uma camada extra de indireção que atrasa o processo de diagnóstico

... uma vez que existe esse famoso aforismo que afirma: "Todos os problemas da ciência da computação podem ser resolvidos por outro nível de indireção". :)

logc
fonte
6

Só porque você está na mesma empresa, não significa que você deve expor tudo a todos. As APIs REST são uma maneira de definir um relacionamento limitado de consumidor / fornecedor entre equipes em uma empresa, com um contrato claro. A Amazon foi pioneira nessa forma de organização.

As APIs também fornecem uma camada de abstração, permitindo que você use um conjunto específico de idiomas - você não quer necessariamente conversar com seus consumidores nos mesmos termos que são usados ​​no seu banco de dados. Você também não quer necessariamente conversar com cada consumidor da mesma maneira.

guillaume31
fonte
3

Você está pensando que o REST é para consultas ao banco de dados e não é. REST representa o estado de algo no momento. O uso de REST altera ou recupera uma representação, mas isso é tudo. Se esse estado se torna disponível pelo banco de dados, isso não importa e ninguém se importa, porque COMO essa representação surge não faz parte do REST e nem as consultas ao banco de dados.

Roubar
fonte
Não estou sugerindo que as consultas ao banco de dados == REST. Certamente o REST é capaz de ser muito mais do que uma camada de abstração de banco de dados, mas nas duas últimas empresas em que trabalhei isso é basicamente tudo o que é - uma camada de abstração de banco de dados. Ele não faz nada além de converter solicitações HTTP em consultas ao banco de dados. E se isso é tudo o que você está fazendo, parece-me que seria melhor atendido pela DBAL. De fato, parece-me que a única razão pela qual algumas pessoas estão usando o REST atualmente é porque está na moda - não porque é a melhor solução disponível para a tarefa em questão.
Neubert
@neubert O DBAL funciona diretamente na Internet, como o REST?
Rob
Certo. Você pode dizer ao MySQL para usar um endereço IP / nome de domínio / porta que pertence a outro computador na Internet. Você pode usar o encapsulamento SSH, bem como (acredito) a autenticação SSL também. Presumivelmente, outros DBMS funcionam da mesma forma.
Neubert 30/03
@neubert: nesse caso, a API REST é um DBAL, não é?
RemcoGerlich
2
@RemcoGerlich - claro, mas usar a API REST como seu DBAL pode estar adicionando uma camada intermediária desnecessária e dificulta o diagnóstico de problemas. Quero dizer, se você usar uma definição suficientemente ampla de DBAL, poderá considerar os SERP do Google como DBAL. Você apenas tem que analisar HTML para obter os dados paginados dos servidores do Google ...
Neubert