Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como criar uma API GraphQL sem servidor para MySQL, Postgres e Aurora


Originalmente postado em Serverless em 2 de julho de 2019



Expor um banco de dados simples por meio de uma API GraphQL requer muito código e infraestrutura personalizados:verdadeiro ou falso?

Para aqueles que responderam “verdadeiro”, estamos aqui para mostrar que criar APIs GraphQL é bastante fácil, com alguns exemplos concretos para ilustrar por que e como.

(Se você já sabe como é fácil criar APIs GraphQL com Serverless, também há muito para você neste artigo.)

GraphQL é uma linguagem de consulta para APIs da web. Há uma diferença fundamental entre uma API REST convencional e APIs baseadas no GraphQL:com o GraphQL, você pode usar uma única solicitação para buscar várias entidades de uma só vez. Isso resulta em carregamentos de página mais rápidos e permite uma estrutura mais simples para seus aplicativos front-end, resultando em uma melhor experiência na Web para todos. Se você nunca usou o GraphQL antes, sugerimos que você confira este tutorial do GraphQL para uma introdução rápida.

A estrutura Serverless é uma ótima opção para APIs GraphQL:com Serverless, você não precisa se preocupar em executar, gerenciar e dimensionar seus próprios servidores de API na nuvem e não precisará escrever nenhum script de automação de infraestrutura. Saiba mais sobre o Serverless aqui. Além disso, o Serverless oferece uma excelente experiência de desenvolvedor independente de fornecedor e uma comunidade robusta para ajudá-lo a construir seus aplicativos GraphQL.

Muitos aplicativos em nossa experiência cotidiana contêm recursos de rede social, e esse tipo de funcionalidade pode realmente se beneficiar da implementação do GraphQL em vez do modelo REST, onde é difícil expor estruturas com entidades aninhadas, como usuários e suas postagens no Twitter. Com o GraphQL, você pode criar um endpoint de API unificado que permite consultar, gravar e editar todas as entidades necessárias usando uma única solicitação de API.

Neste artigo, veremos como criar uma API GraphQL simples com a ajuda da estrutura Serverless, Node.js e qualquer uma das várias soluções de banco de dados hospedados disponíveis por meio do Amazon RDS:MySQL, PostgreSQL e o MySQL Workalike Amazon Aurora.

Acompanhe este repositório de exemplo no GitHub e vamos mergulhar!

Como criar uma API GraphQL com um back-end de banco de dados relacional


Em nosso projeto de exemplo, decidimos usar todos os três bancos de dados (MySQL, PostgreSQL e Aurora) na mesma base de código. Sabemos que isso é um exagero mesmo para um aplicativo de produção, mas queríamos impressioná-lo com a forma como construímos a escala da Web. 😉

Mas, falando sério, sobrecarregamos o projeto apenas para garantir que você encontre um exemplo relevante que se aplique ao seu banco de dados favorito. Se você quiser ver exemplos com outros bancos de dados, informe-nos nos comentários.

Definindo o esquema GraphQL

Vamos começar definindo o esquema da API do GraphQL que queremos criar, o que fazemos no arquivo schema.gql na raiz do nosso projeto usando a sintaxe do GraphQL. Se você não estiver familiarizado com essa sintaxe, dê uma olhada nos exemplos nesta página de documentação do GraphQL.

Para começar, adicionamos os dois primeiros itens ao esquema:uma entidade de usuário e uma entidade de postagem, definindo-as da seguinte forma para que cada usuário possa ter várias entidades de postagem associadas a ele:

digite Usuário {

UUID:String

Nome:Cadeia

Postagens:[Post]

}

digite Postagem {

UUID:String

Texto:Cadeia

}


Agora podemos ver como são as entidades User e Post. Mais tarde, garantiremos que esses campos possam ser armazenados diretamente em nossos bancos de dados.

Em seguida, vamos definir como os usuários da API consultarão essas entidades. Embora possamos usar os dois tipos de GraphQL User e Post diretamente em nossas consultas do GraphQL, é uma prática recomendada criar tipos de entrada para manter o esquema simples. Então vamos em frente e adicionamos dois desses tipos de entrada, um para as postagens e outro para os usuários:

entrada UserInput {

Nome:Cadeia

Postagens:[PostInput]

}

entrada PostInput {

Texto:Cadeia

}


Agora vamos definir as mutações - as operações que modificam os dados armazenados em nossos bancos de dados por meio de nossa API GraphQL. Para isso criamos um tipo Mutation. A única mutação que usaremos por enquanto é createUser. Como estamos usando três bancos de dados diferentes, adicionamos uma mutação para cada tipo de banco de dados. Cada uma das mutações aceita a entrada UserInput e retorna uma entidade User:


Também queremos fornecer uma maneira de consultar os usuários, então criamos um tipo de consulta com uma consulta por tipo de banco de dados. Cada consulta aceita uma String que é o UUID do usuário, retornando a entidade User que contém seu nome, UUID, e uma coleção de todos os Pos``t associados:

Por fim, definimos o esquema e apontamos para os tipos Query e Mutation:
schema { query: Query mutation: Mutation }

Agora temos uma descrição completa para nossa nova API GraphQL! Você pode ver o arquivo inteiro aqui.

Definindo manipuladores para a API GraphQL

Agora que temos uma descrição de nossa API GraphQL, podemos escrever o código necessário para cada consulta e mutação. Começamos criando um arquivo handler.js na raiz do projeto, bem ao lado do arquivo schema.gql que criamos anteriormente.

O primeiro trabalho do handler.js é ler o esquema:




A constante typeDefs agora contém as definições para nossas entidades GraphQL. Em seguida, especificamos onde o código para nossas funções ficará. Para manter as coisas claras, criaremos um arquivo separado para cada consulta e mutação:




A constante de resolvedores agora contém as definições de todas as funções da nossa API. Nosso próximo passo é criar o servidor GraphQL. Lembre-se da biblioteca graphql-yoga que exigimos acima? Usaremos essa biblioteca aqui para criar um servidor GraphQL funcional de maneira fácil e rápida:




Por fim, exportamos o manipulador GraphQL junto com o manipulador GraphQL Playground (o que nos permitirá experimentar nossa API GraphQL em um navegador da web):




Ok, terminamos com o arquivo handler.js por enquanto. Em seguida:escrever código para todas as funções que acessam os bancos de dados.

Escrevendo código para as consultas e as mutações

Agora precisamos de código para acessar os bancos de dados e alimentar nossa API GraphQL. Na raiz do nosso projeto, criamos a seguinte estrutura para nossas funções de resolução do MySQL, com os outros bancos de dados a seguir:


Consultas comuns
Na pasta Common, preenchemos o arquivo mysql.js com o que precisaremos para a mutação createUser e a consulta getUser:uma consulta init, para criar tabelas para Users e Posts se ainda não existirem; e uma consulta de usuário, para retornar os dados de um usuário ao criar e consultar um usuário. Usaremos isso na mutação e na consulta.

A consulta init cria as tabelas Users e Posts da seguinte forma:


A consulta getUser retorna o usuário e suas postagens:

Ambas as funções são exportadas; podemos então acessá-los no arquivo handler.js.
Escrevendo a mutação

Hora de escrever o código para a mutação createUser, que precisa aceitar o nome do novo usuário, bem como uma lista de todos os posts que pertencem a ele. Para fazer isso, criamos o arquivo resolver/Mutation/mysql_createUser.js com uma única função func exportada para a mutação:


A função de mutação precisa fazer as seguintes coisas, em ordem:

  1. Conecte-se ao banco de dados usando as credenciais nas variáveis ​​de ambiente do aplicativo.

  2. Insira o usuário no banco de dados usando o nome de usuário fornecido como entrada para a mutação.

  3. Insira também quaisquer postagens associadas ao usuário, fornecidas como entrada para a mutação.

  4. Retorne os dados do usuário criado.

Veja como fazemos isso no código:


Você pode ver o arquivo completo que define a mutação aqui.
Escrevendo a consulta

A consulta getUser tem uma estrutura semelhante à mutação que acabamos de escrever, mas esta é ainda mais simples. Agora que a função getUser está no namespace Common, não precisamos mais de nenhum SQL personalizado na consulta. Então, criamos o arquivo resolver/Query/mysql_getUser.js da seguinte forma:


Você pode ver a consulta completa neste arquivo.
Reunindo tudo no arquivo serverless.yml

Vamos dar um passo atrás. Atualmente temos o seguinte:

  • Um esquema de API GraphQL.

  • Um arquivo handler.js.

  • Um arquivo para consultas de banco de dados comuns.

  • Um arquivo para cada mutação e consulta.

A última etapa é conectar tudo isso através do arquivo serverless.yml. Criamos um serverless.yml vazio na raiz do projeto e começamos definindo o provedor, a região e o tempo de execução. Também aplicamos a função LambdaRole IAM (que definimos posteriormente aqui) ao nosso projeto:


Em seguida, definimos as variáveis ​​de ambiente para as credenciais do banco de dados:

Observe que todas as variáveis ​​fazem referência à seção personalizada, que vem a seguir e contém os valores reais das variáveis. Observe que a senha é uma senha terrível para seu banco de dados e deve ser alterada para algo mais seguro (talvez p@ssw0rd 😃):

Quais são essas referências depois de Fn::GettAtt, você pergunta? Aqueles se referem a recursos de banco de dados:

O arquivo resource/MySqlRDSInstance.yml define todos os atributos da instância MySQL. Você pode encontrar seu conteúdo completo aqui.
Finalmente, no arquivo serverless.yml definimos duas funções, graphql e playground. A função graphql lidará com todas as solicitações da API, e o endpoint do playground criará uma instância do GraphQL Playground para nós, o que é uma ótima maneira de experimentar nossa API GraphQL em um navegador da web:


Agora o suporte ao MySQL para nosso aplicativo está completo!
Você pode encontrar o conteúdo completo do arquivo serverless.yml aqui.

Adicionando suporte ao Aurora e PostgreSQL

Já criamos toda a estrutura necessária para suportar outros bancos de dados neste projeto. Para adicionar suporte para Aurora e Postgres, precisamos apenas definir o código para suas mutações e consultas, o que fazemos da seguinte forma:

  1. Adicione um arquivo de consultas comuns para Aurora e Postgres.

  2. Adicione a mutação createUser para ambos os bancos de dados.

  3. Adicione a consulta getUser para ambos os bancos de dados.

  4. Adicione a configuração no arquivo serverless.yml para todas as variáveis ​​de ambiente e recursos necessários para ambos os bancos de dados.

Neste ponto, temos tudo o que precisamos para implantar nossa API GraphQL, desenvolvida com MySQL, Aurora e PostgreSQL.

Como implantar e testar a API GraphQL


A implantação de nossa API GraphQL é simples.

  • Primeiro, executamos o npm install para colocar nossas dependências no lugar.

  • Em seguida, executamos npm run deploy, que configura todas as nossas variáveis ​​de ambiente e executa a implantação.

  • Sob o capô, esse comando executa a implantação sem servidor usando o ambiente certo.

É isso! Na saída da etapa de implantação, veremos o endpoint de URL para nosso aplicativo implantado. Podemos emitir solicitações POST para nossa API GraphQL usando essa URL, e nosso Playground (com o qual brincaremos em um segundo) está disponível usando GET na mesma URL.

Experimentando a API no GraphQL Playground

O GraphQL Playground, que é o que você vê ao visitar esse URL no navegador, é uma ótima maneira de experimentar nossa API.



Vamos criar um usuário executando a seguinte mutação:
mutation { mysql_createUser( input: { Name: "Cicero" Posts: [ { Text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." } { Text: "Proin consequat mauris orci, ut consequat purus efficitur vel." } ] } ) { Name UUID } }

Nesta mutação, chamamos a API mysql_createUser, fornecemos o texto das postagens do novo usuário e indicamos que queremos recuperar o nome do usuário e o UUID como resposta.

Cole o texto acima no lado esquerdo do Playground e clique no botão Play. À direita, você verá a saída da consulta:




Agora vamos consultar este usuário:
query { mysql_getUser(uuid: "f5593682-6bf1-466a-967d-98c7e9da844b") { Name UUID } }

Isso nos devolve o nome e o UUID do usuário que acabamos de criar. Arrumado!




Podemos fazer o mesmo com os outros backends, PostgreSQL e Aurora. Para isso, basta substituir os nomes da mutação por postgres_createUser ou aurora_createUser, e as consultas por postgres_getUser ou aurora_getUser. Experimente você mesmo! (Lembre-se de que os usuários não são sincronizados entre os bancos de dados, portanto, você só poderá consultar os usuários que criou em cada banco de dados específico.)

Comparando as implementações do MySQL, PostgreSQL e Aurora


Para começar, as mutações e consultas são exatamente iguais no Aurora e no MySQL, pois o Aurora é compatível com MySQL. E há apenas diferenças mínimas de código entre esses dois e a implementação do Postgres.

Na verdade, para casos de uso simples, a maior diferença entre nossos três bancos de dados é que o Aurora está disponível apenas como um cluster. A menor configuração disponível do Aurora ainda inclui uma réplica somente leitura e uma réplica de gravação, portanto, precisamos de uma configuração em cluster mesmo para esta implantação básica do Aurora.

O Aurora oferece desempenho mais rápido que o MySQL e o PostgreSQL, devido principalmente às otimizações de SSD que a Amazon fez no mecanismo de banco de dados. À medida que seu projeto cresce, você provavelmente descobrirá que o Aurora oferece melhor escalabilidade de banco de dados, manutenção mais fácil e melhor confiabilidade em comparação com as configurações padrão do MySQL e PostgreSQL. Mas você também pode fazer algumas dessas melhorias no MySQL e no PostgreSQL se ajustar seus bancos de dados e adicionar replicação.

Para projetos de teste e playgrounds recomendamos MySQL ou PostgreSQL. Eles podem ser executados em instâncias db.t2.micro RDS, que fazem parte do nível gratuito da AWS. Atualmente, o Aurora não oferece instâncias db.t2.micro, portanto, você pagará um pouco mais para usar o Aurora para este projeto de teste.

Uma nota final importante


Lembre-se de remover sua implantação sem servidor depois de terminar de experimentar a API GraphQL para não continuar pagando por recursos de banco de dados que não está mais usando.

Você pode remover a pilha criada neste exemplo executando npm run remove na raiz do projeto.

Feliz experimentando!

Resumo


Neste artigo, orientamos você na criação de uma API GraphQL simples, usando três bancos de dados diferentes ao mesmo tempo; embora isso não seja algo que você faria na realidade, isso nos permitiu comparar implementações simples dos bancos de dados Aurora, MySQL e PostgreSQL. Vimos que a implementação para todos os três bancos de dados é aproximadamente a mesma em nosso caso simples, exceto pequenas diferenças na sintaxe e nas configurações de implantação.

Você pode encontrar o projeto de exemplo completo que estamos usando neste repositório do GitHub. A maneira mais fácil de experimentar o projeto é clonar o repositório e implantá-lo de sua máquina usando npm run deploy.

Para obter mais exemplos de API GraphQL usando Serverless, confira o repositório serverless-graphql.

Se você quiser saber mais sobre como executar APIs GraphQL sem servidor em escala, poderá aproveitar nossa série de artigos "Executando um endpoint GraphQL escalável e confiável com Serverless"

Talvez o GraphQL não seja o seu jam e você prefira implantar uma API REST? Nós temos o que você precisa:confira esta postagem do blog para alguns exemplos.

Questões? Comente esta postagem ou crie uma discussão em nosso fórum.

Publicado originalmente em https://www.serverless.com.