Microsserviços e procedimentos armazenados

34

Os procedimentos armazenados são considerados práticas inadequadas em uma arquitetura de microsserviço?

Aqui estão os meus pensamentos:

  • a maioria dos livros sobre microsserviços recomenda um banco de dados por microsserviço. Os procedimentos armazenados normalmente funcionam em um banco de dados monolítico.

  • Novamente, a maioria dos livros de arquitetura de microsserviço declara que eles devem ser autônomos e acoplados livremente. O uso de procedimentos armazenados escritos, digamos especificamente no Oracle, une fortemente o microsserviço a essa tecnologia.

  • a maioria dos livros de arquitetura Microservice (que eu li) recomendam que microservices deve ser orientada para negócios (projetado usando Domain-Driven Design (DDD)). Movendo a lógica de negócios para os procedimentos armazenados no banco de dados, esse não é mais o caso.

Alguma idéia sobre isso?

Johnny Alpha
fonte
10
@ RandomUs1r desculpe, isso não faz sentido para mim. Por que a estrutura do banco de dados precisa ser não relacional? Claro, pode ter referências externas, mas sua estrutura interna pode muito bem ser 100% relacional
IMil 17/09/17
12
O problema com seus pontos é que todas as suas instalações estão erradas. A afirmação de que os microsserviços devem ser autônomos e fracamente acoplados significa, antes de tudo, que eles devem ser fracamente acoplados entre si ; como você gerencia o acoplamento de componentes internos é uma questão diferente - e de importância secundária (mas não sem importância) - especialmente se você puder apenas substituir todo o microsserviço em uma atualização. Portanto, não há razão para que você não possa usar sprocs dentro desses limites. Além disso, o DDD não proíbe sprocs ou mistura de paradigmas; alguns aspectos de alguns problemas não são mais adequados para OO.
Filip Milovanović
3
O quão monolítico seu banco de dados está relacionado ao seu Design e implementação de dados, não tem nada a ver com o uso ou não de procedimentos armazenados.
RBarryYoung 17/09
5
"Procedimentos armazenados normalmente funcionam em um banco de dados monolítico." Você deve considerar o descarte de qualquer informação ou conselho que receber de qualquer fonte que tenha compartilhado esse "fato" com você.
StingyJack 18/09
3
@ RandomUs1r Umm não, a única coisa que você realmente perde é que você não pode usar restrições de chave estrangeira nas chaves de referência - o que é o objetivo dos microsserviços. Por um lado, a idéia de que os bancos de dados NoSql são de alguma forma magicamente mais rápidos foi refutada repetidamente, mas mesmo que fossem mais rápidos (eles não são), você também obtém toda a infraestrutura, conhecimento e código existentes gratuitamente - o que é enorme . O CERN e muitos outros gerenciam terabytes de dados usando bancos de dados relacionais. Os bancos de dados NoSql têm seu uso, mas são independentes de você usar microsserviços ou não.
Voo

Respostas:

45

Não há nada que proíba ou argumente explicitamente contra o uso de procedimentos armazenados com microsserviços.

Isenção de responsabilidade: não gosto de procedimentos armazenados do POV de um desenvolvedor, mas isso não está relacionado aos microsserviços de forma alguma.

Os procedimentos armazenados normalmente funcionam em um banco de dados monolítico.

Eu acho que você está sucumbindo a uma falácia lógica.

Atualmente, os procedimentos armazenados estão em declínio. A maioria dos procedimentos armazenados que ainda estão em uso são de uma base de código mais antiga, mantida por aí. Naquela época, os bancos de dados monolíticos também eram muito mais prevalentes em comparação com quando os microsserviços se tornaram populares.

Procs armazenados e bancos de dados monolíticos ocorrem em bases de código antigas, e é por isso que você as vê juntas com mais frequência. Mas isso não é um nexo de causalidade. Você não usa procs armazenados porque possui um banco de dados monololítico. Você não possui um banco de dados monolítico porque usa procs armazenados.

a maioria dos livros sobre microsserviços recomenda um banco de dados por microsserviço.

Não há nenhuma razão técnica para que esses bancos de dados menores não possam ter procedimentos armazenados.

Como mencionei, não gosto de procs armazenados. Acho-os pesados ​​e resistentes à manutenção futura. Eu acho que espalhar sprocs por muitos bancos de dados pequenos agrava ainda mais os problemas que eu já não gosto. Mas isso não significa que não possa ser feito.

Novamente, a maioria dos livros de arquitetura de microsserviço declara que eles devem ser autônomos e acoplados livremente. O uso de procedimentos armazenados escritos digamos especificamente no Oracle, acopla firmemente o microsserviço a essa tecnologia.

Por outro lado, o mesmo argumento pode ser feito para qualquer ORM que seu microsserviço use. Nem todo ORM também suporta todos os bancos de dados. O acoplamento (especificamente seu aperto) é um conceito relativo. É uma questão de ser o mais solto possível.

Os Sprocs sofrem de acoplamento apertado em geral, independentemente dos microsserviços. Eu recomendaria contra sprocs em geral, mas não particularmente porque você está usando microsserviços. É o mesmo argumento de antes: eu não acho que os sprocs sejam o caminho a seguir (em geral), mas isso pode ser apenas o meu viés, e não está relacionado aos microsserviços.

a maioria dos livros de msa (que eu li) recomenda que os microsserviços sejam orientados para os negócios (projetados usando o ddd). Movendo a lógica de negócios para os procedimentos armazenados no banco de dados, esse não é mais o caso.

Essa sempre foi minha queixa principal sobre sprocs: lógica de negócios no banco de dados. Mesmo quando não é a intenção, tende a acabar sempre assim.

Mas, novamente, essa queixa existe independentemente de você usar microsserviços ou não. A única razão pela qual parece um problema maior é porque os microsserviços pressionam você a modernizar toda a arquitetura e os sprocs não são mais os preferidos nas arquiteturas modernas.

Flater
fonte
4
Não tenho certeza se é correto dizer que os microsserviços o incentivam a modernizar toda a arquitetura. Na maioria das vezes, eles acabam sendo uma camada fina sobre um gigante de uma bagunça de código mal planejado. Eles podem ser muito bons quando bem executados, mas na verdade não ajudam a codificar melhor do que qualquer outra arquitetura. Ainda assim, boa resposta. Você recebeu um +1 de mim.
T. Sar - Restabelece Monica
11
@ T.Sar moderno não é o mesmo que melhor. Refatorar (para microsserviços ou qualquer outra coisa) significa mudança. A mudança obriga a usar suas idéias atuais. Esperamos que sejam melhores ideias.
candied_orange 16/09
2
@ T.Sar: Hacks são atemporais, e você geralmente pode abusar de qualquer sistema (moderno ou não) para fazer algo que ele tecnicamente possa lidar, mas que nunca foi planejado. Os microsserviços pedem que você faça de maneira diferente (e, portanto, reavalie algumas abordagens antigas), mas eles não podem aplicá- la universalmente . Com a aplicação universal, você geralmente sofre no departamento de casos adicionais de compatibilidade / válido.
Flater 16/09
4
@candied_orange "moderno não é o mesmo que melhor" - acho que concordo plenamente com isso. Muito bom ponto.
T. Sar - Restabelece Monica
3
Moderno nem sequer é sinônimo de "adequado".
Laiv 17/09
24

Para escrever software, é necessário que você se junte firmemente a uma tecnologia.

No mínimo, para o ambiente de tempo de execução fornecido pela linguagem de programação em desenvolvimento.

De maneira mais geral, você descobrirá que seu microsserviço está fortemente associado a várias tecnologias:

  • Network Service Framework para fornecer implementações de protocolo HTTP / SSL / SOAP de alto nível
  • Repositório / ORM / DAO Framework para fornecer persistência.
  • Estruturas de manipulação de dados para fornecer ferramentas para trabalhar com dados.
  • Process / Threading / OS Framework para fornecer acesso aos recursos do SO, como multitarefas, sistema de arquivos, memória, computação da GPU, placas de expansão, etc.

E isso é fazer um micro-serviço básico.

Procedimentos armazenados

Um procedimento armazenado é simplesmente outra tecnologia que você pode optar por usar ou não. Magicamente não torna seu código monolítico ou micro.

O que é, porém, é:

  • Outra tecnologia. Cada tecnologia presente no aplicativo diminui a probabilidade de que qualquer programador possa ler, entender e fazer escolhas sábias de design para esse mix de tecnologia.
  • Uma linguagem usando um paradigma de programação diferente. É muito fácil para os não especialistas tentarem forçar sua própria perspectiva imperativa, funcional, OO, etc ..., o que geralmente leva a resultados menos que estelares.
  • Uma API. Que deve ser mantido como qualquer outra classe na base de código. Isso também significa que o banco de dados está fornecendo uma interface não genérica. Isso dificulta a substituição do mecanismo de banco de dados e a aplicação transparente de comportamentos genéricos, como no cache de memória.
  • Um artefato. Que deve ser versionado, testado e implantado. Isso pode ser feito, mas os bancos de dados são artefatos vivos que requerem uma abordagem diferente. Normalmente, você não pode simplesmente excluir o original e substituí-lo. Muitas vezes, é necessária uma cuidadosa orquestração das alterações ao longo do tempo para migrar o sistema para o estado desejado.

Cada um destes é um custo real. Em alguns casos, o custo é justificável; em outros, não.

Você pagaria quase o mesmo conjunto de custos hospedando um mecanismo de script. A única redução é que você pode escolher o mesmo paradigma de programação que a linguagem host.

Logíca de negócios

Mover regras de negócios para o banco de dados é uma prática recomendada. Só não por causa dos procedimentos armazenados.

É uma prática ruim, porque o banco de dados e a lógica de negócios operam em diferentes níveis de cisalhamento.

  • Um banco de dados em aplicativos maduros pode ser usado por décadas. Geralmente esses sistemas terão o mecanismo atualizado periodicamente, mas o próprio banco de dados foi migrado. Não foi morto e reconstruído desde o início. Não há razão para que um micro serviço não possa ter a mesma duração de vida.

  • Compare décadas com a rapidez com que as regras de negócios mudam. De acordo com a minha experiência, uma regra de negócios antiga talvez tenha alguns anos, mas a maioria muda rapidamente, e você nunca pode dizer qual será a próxima. Um novo requisito de um regulador, um produto antigo sendo descomissionado, alterações no cabeçalho da carta, alterações na quantidade de funcionários que se reportam a um chefe, etc, etc, etc ...

Se a lógica de negócios for distribuída pelas camadas de cisalhamento, particularmente em uma camada mais lenta e de vida mais longa, ela gerará resistência à mudança. Isto não é necessariamente uma coisa ruim. Afinal, o único banco de dados que não possui lógica de negócios é um armazenamento triplo.

O simples ato de especificar um esquema de tabela está movendo a lógica de negócios para o banco de dados.

Arquitetura

Você está usando a ferramenta apropriada para o problema apropriado, sem precisar de muitas ferramentas nem dificultando a solução para criar e manter uma solução.

Isto não é fácil.

Mas vamos pensar o impensável, como você manteria a lógica de negócios distribuída em vários idiomas?

  • Um catálogo ... para que cada implementação de regra de negócios possa ser rastreada e mantida.
  • Testes ... que poderiam ser usados ​​em cada regra de negócios, independentemente de onde e como ela foi implementada.
  • Uma implementação de referência .. para que, quando forem encontradas discrepâncias, exista uma fonte de verdade (ou pelo menos uma fonte de debate).

Mas isso também tem um custo.

  • É melhor permitir que as regras de negócios tenham muitas implementações? Cada um pode tirar proveito das habilidades da equipe e das disposições da estrutura, mas necessitando de controles rígidos de qualidade para evitar muitos pequenos caprichos?
  • Ou é melhor ter uma única fonte de verdade, escrita em um único idioma? Indiscutivelmente mais barato de implementar, mas também uma única fonte de falha, ele mesmo um componente monolítico que resiste à mudança em face de diferentes plataformas, estruturas ou ferramentas ainda a serem inventadas?
Kain0_0
fonte
8

Prefácio minha resposta dizendo que, na verdade, mantenho alguns microsserviços que usam procedimentos armazenados. Também escrevi muitos procedimentos armazenados em vários pontos da minha carreira e definitivamente concordo que as coisas podem dar muito, muito errado se forem usadas incorretamente.

Portanto, a resposta curta é que não, os procedimentos armazenados não são inerentemente ruins em uma arquitetura de microsserviço. Mas você precisa entender:

  1. Você está adicionando obstáculos à substituição de mecanismos de armazenamento. Se algumas características operacionais ou de desempenho ou limitações de recursos exigirem a troca de mecanismos de armazenamento, o custo será maior porque você estará escrevendo e testando muitos códigos novos. A execução de mais de um mecanismo de armazenamento (durante uma fase de migração ou para isolar atividades com base nas necessidades de desempenho) pode apresentar problemas de consistência, a menos que você use a confirmação de duas fases (2PC), que possui problemas de desempenho.
  2. Você tem outra API para manter, o que significa que suas dependências podem quebrar. Adicionar, remover ou alterar os tipos de parâmetros nos procedimentos pode quebrar o código existente. O mesmo acontece com tabelas e consultas, mas suas ferramentas podem ser menos úteis para rastrear onde as coisas podem dar errado. Problemas com procedimentos armazenados geralmente são encontrados em tempo de execução, muito tarde no processo de desenvolvimento / implantação.
  3. Suas permissões de banco de dados ficaram mais complicadas. Um procedimento é executado como usuário conectado ou como outra função? Você precisa pensar sobre isso e gerenciar (espero que de forma automatizada).
  4. Você precisa poder migrar para novas versões com segurança. Muitas vezes, um procedimento deve ser descartado e recriado. Mais uma vez, as permissões podem causar alguns problemas para você.
  5. A reversão de uma migração com falha pode significar um esforço extra. Quando o ambiente de produção é separado dos desenvolvedores, as coisas ficam ainda mais desafiadoras.

Estes são alguns usos de procedimentos armazenados que acho que valem a pena:

  1. Aplicação do histórico de edição (logs de auditoria). Os gatilhos são comumente usados ​​para esse fim, e os gatilhos são procedimentos armazenados. Em alguns bancos de dados, também é possível proibir inserções e atualizações inteiramente para a função do aplicativo: os clientes executam procedimentos que são executados como uma função diferente com permissões apropriadas e que impõem todo o comportamento necessário.
  2. Extensão de restrições de verificação. Isso pode levá-lo ao território da lógica de negócios, mas há casos em que as ferramentas internas de restrição de um banco de dados podem não ser suficientes para o que você precisa. Muitas vezes, a melhor maneira de expressar cheques é com código imperativo, e você corre o risco de permitir a entrada de dados incorretos se depender do seu aplicativo para fazer isso por você.
  3. Encapsulamento de consultas complexas quando uma exibição é inadequada ou muito complicada. Eu já vi alguns casos em que uma visão correta requer SQL extremamente complexo que pode ser expresso de maneira muito mais compreensível em um procedimento armazenado. Provavelmente isso é raro, mas ocorre.

Em geral, sugiro que você experimente as visualizações primeiro e recorra aos procedimentos somente quando necessário. As visualizações bem projetadas podem realmente funcionar como uma API, abstraindo os detalhes de como as tabelas subjacentes são consultadas. Aumentar sua API (visualizações) com procedimentos armazenados faz sentido em algumas circunstâncias. É até possível emitir JSON diretamente de uma consulta SQL, ignorando toda a bagunça de mapear dados dos resultados da consulta para o modelo de dados do seu aplicativo. Se essa é uma boa ideia, é algo que você pode determinar com base em suas próprias necessidades.

Como você já deve gerenciar os recursos do banco de dados (esquema, permissões etc.) por meio de alguma ferramenta automatizada, não, os procedimentos armazenados não são inerentemente ruins para os microsserviços.

ngreen
fonte
Eu acho que todos os seus primeiros pontos também se aplicam, se você escrever a lógica de negócios em, por exemplo, um Java-Framework. A mudança do DB-Engine alterará as características de desempenho e exigirá novo teste e talvez reescrever as instruções. Se você escrever as Instruções SQL, por exemplo, como Strings em seu aplicativo, terá o mesmo problema ao alterar variáveis, quebrando coisas. Você precisa decidir se o aplicativo usa um usuário técnico ou usuários individuais para se conectar ao banco de dados e assim por diante ...
Falco,
@ Falco Eu acho que se você estiver usando JPA exclusivamente, não deve ser muito difícil alterar bancos de dados. Definitivamente, o desempenho pode variar substancialmente e sempre precisa ser testado. Alguns serviços que mantenho não são "micro" no sentido de que podem digitalizar ou agregar milhões ou bilhões de pontos de dados e retornar conjuntos de dados arbitrariamente grandes (geralmente paginados). Não consigo imaginar usar o JPA para eles, mas posso imaginar alterando os mecanismos de banco de dados subjacentes (e reescrevendo o SQL), mantendo a mesma API.
ngreen 20/09
4

Procedimentos armazenados são detalhes de implementação. Funções de banco de dados, lambdas ou um script de shell armazenado em algum lugar no sistema de arquivos são todos detalhes da implementação e irrelevantes para a arquitetura.

a maioria dos livros sobre microsserviços recomenda um banco de dados por microsserviço.

Ok, para que possamos codificar os procedimentos armazenados nesses bancos de dados.

mais uma vez, a maioria dos livros de arquitetura de microsserviço declara que eles devem ser autônomos e com pouca conexão

Entre os recursos de negócios, os ciclos de vida do desenvolvimento, o gerenciamento, as implantações, os locais das equipes etc. Nada a ver com os detalhes da implementação. Os microsserviços não resolvem um problema técnico (exatamente o oposto). Eles vêm para resolver problemas com a administração e o tempo de colocação no mercado. É uma estratégia, não uma tática. Uma maneira de obter falhas com o menor custo possível. Se um determinado recurso de negócios é inútil, nós o descartamos sem prejudicar outros recursos, implantações, gerenciamento de projetos, lançamentos ...

Observe que a "divisão" já atua como um agente de desacoplamento. Digamos que temos dois serviços, A é suportado pelo Oracle e B pelo MongoDB. Se não violarmos a regra de ouro da dissociação, deve ser possível descartar o A + Oracle com efeitos colaterais desprezíveis em B.

O uso de procedimentos armazenados escritos digamos especificamente no Oracle, acopla firmemente o microsserviço a essa tecnologia.

Isso pode causar o bloqueio do fornecedor. Muitas vezes, o fornecedor é imposto pelo negócio por razões históricas ou contratuais 1 . É importante saber como não bloquear nosso código para o fornecedor. Por exemplo, alguns ORM e estruturas implementam uma nova linguagem de consulta que oculta as funções e os recursos internos do banco de dados.

Embora nossos serviços sejam suficientemente micro, o aprisionamento de fornecedores não é mais um problema, pois afeta uma pequena parte do todo. Uma pequena peça que deve ser possível ser substituída (ou isolada) rapidamente.

a maioria dos livros da MSA (que eu li) recomenda que os microsserviços sejam orientados para os negócios (projetados usando DDD).

Deve ser direcionado aos negócios e aqui está a coisa. Nem todas as empresas aproveitam o DDD. DDD e microsserviços se sobrepõem em muitos pontos, mas eles não são causa-efeito. Poderíamos acabar com um ecossistema de microsserviços composto por serviços anêmicos. Ou composto de uma mistura de ambos: serviços implementando um domínio complexo e serviços anêmicos mudos, fornecendo POJOs diretamente do DB. Não há nada de errado nisso.

Em relação aos livros, eles se concentram apenas na execução da estratégia. As táticas - como tirar proveito da computação distribuída - como fazê-la funcionar com sucesso, mas são (geralmente) agnósticas à estratégia. As estratégias variam de empresa para empresa e raramente dependem dos desenvolvedores. Portanto, ainda precisamos extrapolar e adaptar o que os livros dizem às nossas necessidades, exigências e restrições específicas. O objetivo é tornar a estratégia de negócios rentável e sustentável.

Lembre-se sempre de que qualquer arquitetura é um meio para atingir um fim. As regras de negócios. Não construímos ecossistemas de microsserviços para moda ou amor à arte.

Laiv
fonte
1

Realmente não tem nada a ver com microsserviços.

Os procedimentos armazenados podem fazer sentido se o seu serviço tiver uma arquitetura em camadas 'antiga' na qual o DB é a base do serviço, com camadas de acesso a dados e lógica de negócios no topo. A interface entre o serviço e o banco de dados em uma arquitetura desse tipo é muito específica para os detalhes mais internos do serviço. Normalmente, haverá adaptadores específicos de serviço para cada tipo de banco de dados suportado, e a especificidade da API exposta pelo adaptador possibilita o uso de procedimentos armazenados nas camadas subjacentes.

Existem muitos problemas com arquiteturas como essa. Mais importante ainda, torna a maior parte da lógica muito difícil para o teste de unidade. Essas arquiteturas não são mais favoráveis.

Se você estiver usando uma "arquitetura limpa", "arquitetura de cebola" ou algo semelhante, o banco de dados será uma dependência injetada , especificada nas camadas externas. Como é definido nas camadas externas, a interface fornecida para o banco de dados deve ser genérica . Ele não pode refletir os detalhes mais internos do serviço, porque esses detalhes devem estar ocultos das camadas mais externas da arquitetura. Definir uma interface genérica de procedimento armazenado que possa funcionar com qualquer banco de dados ou equipamento de teste de unidade é incrivelmente difícil e não é realmente necessário; portanto, os procedimentos armazenados geralmente não são práticos nesses tipos de arquitetura.

A relação com os microsserviços é que os microsserviços são novos e ascendentes - não fazemos mais monólitos - e que esses novos estilos arquitetônicos também são ascendentes - não fazemos mais camadas planas.

Matt Timmermans
fonte