API REST sem servidor "no joelho em 5 minutos"

Olá Habr! Hoje, continuamos a discussão sobre as oportunidades que o Amazon Web Services nos fornece e como usá-las na solução de problemas de aplicativos.

Usando um exemplo simples, considere criar em apenas alguns minutos nossa própria API REST auto-escalável sem servidor com análise de caso - obtendo uma lista para um recurso.

Interessante? Então vá para o corte!


(Fonte)

Em vez de se juntar


Não usaremos nenhum banco de dados para analisar o exemplo; em vez disso, nossa fonte de informações será um arquivo de texto sem formatação no AWS S3.

  • Portanto, suponha que no AWS S3 tenhamos um arquivo de texto com cabeçalhos e algum processo grave informações nele.
  • Criaremos uma API de nuvem que retornará uma resposta JSON como uma solicitação GET com o parâmetro passado.
  • Ao mesmo tempo, dependendo da complexidade das tarefas e, como conseqüência, do aumento dos requisitos para o poder de processamento dos recursos, você não precisa se preocupar com isso, porque o serviço é totalmente escalável automaticamente. E isso significa que você não precisa de administração, alocação e gerenciamento de servidores, basta fazer upload do seu código e executá-lo.

Arquitetura do sistema em desenvolvimento




Componentes do Amazon Web Services usados:

  • Amazon S3 - armazenamento de objetos, que permite armazenar quantidades quase ilimitadas de informações;
  • Gerenciamento de acesso e identidade da AWS (IAM) - Um serviço que fornece a capacidade de controlar com segurança o acesso aos serviços e recursos da AWS. Usando o IAM, você pode criar, gerenciar, gerenciar usuários e grupos da AWS e usar permissões para conceder ou negar acesso aos recursos da AWS;
  • O AWS Lambda é um serviço que permite executar código sem fazer backup e configurar servidores. Todo o poder de computação é dimensionado automaticamente para cada chamada. A taxa é cobrada com base no número de solicitações de recursos e sua duração, ou seja, tempo durante o qual o código é executado.
    O nível de acesso gratuito (nível gratuito) implica 1 milhão de solicitações por mês de graça e 400K Gb-s. Idiomas suportados: Node.js, Java, C #, Go, Python, Ruby, PowerShell
    . Vamos usar o Python:

    • A biblioteca boto3 é um AWS SDK para Python que permite interagir com vários serviços da Amazon;
  • O Amazon API Gateway é um serviço de desenvolvedor totalmente gerenciado, projetado para criar, publicar, manter, monitorar e proteger APIs em qualquer escala. Além da capacidade de usar várias versões da mesma API (etapas) para depuração, refinamento e teste, o serviço permite criar APIs REST sem servidor usando o AWS Lambda. O Lambda executa código em uma infraestrutura de computação altamente acessível, eliminando a necessidade de distribuição, dimensionamento e gerenciamento de servidores.
    A camada gratuita da API HTTP / REST inclui um milhão de chamadas de API por mês durante 12 meses

Preparação de dados


Um arquivo de texto com uma guia será usado como um delimitador de campo como fonte de informações para gerar respostas a uma solicitação GET REST. As informações agora realmente não importam para este exemplo, mas para uso posterior da API, baixei do terminal de negociação Quik uma tabela de negociações atuais de títulos denominados em rublos russos, salvei-os em bonds.txt e coloquei esse arquivo em um bucket do AWS S3 especialmente criado.

Um exemplo das informações recebidas é mostrado na figura abaixo:



Em seguida, você precisa escrever uma função que leia as informações do arquivo bonds.txt, analise-as e emita-as mediante solicitação. O AWS Lambda se sairá bem com isso. Mas primeiro, você precisará criar uma nova função que permita que a função Lambda criada leia as informações do bucket localizado no AWS S3.

Criar funções para o AWS Lambda


  1. No console de gerenciamento da AWS, acesse o serviço AWS IAM e, em seguida, na guia "Funções", clique no botão "Criar função";

    Adicionando uma nova função

  2. A função que estamos criando agora será usada pelo AWS Lambda para ler as informações do AWS S3. Portanto, na próxima etapa, selecione "Selecionar tipo de confiável" -> "Serviço Aws" e "Escolha o serviço que usará essa função" -> "Lambda" e clique no botão "Avançar: Permissões"

    Função de serviço Lambda

  3. Agora você precisa definir as políticas de acesso para os recursos da AWS que serão usados ​​na função recém-criada. Porque a lista de políticas é bastante impressionante. Usando o filtro de políticas, indicamos "S3". Como resultado, obtemos uma lista filtrada para o serviço S3. Observe a caixa de seleção ao lado da política "AmazonS3ReadOnlyAccess" e clique no botão "Próximo: Tags".

    Políticas para funções

  4. A etapa (Adicionar tags (opcional)) é opcional, mas você pode especificar tags para Funções, se desejar. Não faremos isso e passaremos para o próximo passo - Visualizar. Aqui você precisa definir o nome da função - "ForLambdaS3-ReadOnly", adicionar uma descrição e clicar no botão "Criar função".

    Funções do título


Tudo, o papel foi criado e podemos usá-lo em outros trabalhos.

Crie um novo recurso no AWS Lambda


  1. Acesse o serviço AWS Lambda e clique no botão "Criar função":

    Criação de Função


    Preencha todos os campos, conforme mostrado na captura de tela abaixo:

    • Nome - "getAllBondsList";
    • Tempo de execução - "Python 3.6"
    • Função - "Escolha uma função existente"
    • Função existente - aqui selecionamos a função que criamos acima - ForLambdaS3-ReadOnly

    Nome e escolha da função

  2. Resta apenas escrever o código da função e verificar seu desempenho em várias execuções de teste. Deve-se notar que o principal componente de qualquer função Lambda (se você usa Python) é a biblioteca boto3:

    import boto3 s3 = boto3.resource('s3') bucket = s3.Bucket('your-s3-bucket') obj = bucket.Object(key = 'bonds.txt') response = obj.get() 

    A idéia básica da nossa função Python é a seguinte:

    • Abra o arquivo bonds.txt;
    • Leia os cabeçalhos das colunas;
    • Quebrar recordes por página (10 coleções no nosso caso);
    • Selecione a página desejada;
    • Mapeie o nome das colunas e registros;
    • Dê o resultado na forma de coleções.

    Não dedicaremos muito tempo ao código de função e à implementação técnica, tudo é bem simples aqui e o código completo está disponível no meu GitHub .

      for i in range(0, len(lines_proc)): d = dict((u''.join(key), u''.join(value)) for (key, value) in zip(headers, lines_proc[i].split("\t"))) response_body.append(d) return { 'statusCode': 200, 'page' : num_page, 'body': response_body } 

    Insira o código (ou escreva o seu próprio :)) no bloco "Código da função" e clique no botão "Salvar" no canto superior direito da tela.

    Inserção de código

  3. Crie eventos de teste. Após inserir o código, a função estará disponível para inicialização e teste. Clique no botão "Teste" e crie alguns eventos de teste: iniciando a função lambda_handler com parâmetros diferentes. Ou seja:

    • Iniciando uma função com o parâmetro 'page': '100';
    • Ativando uma função com o parâmetro 'page': '1000000';
    • Iniciando uma função com o parâmetro 'page': 'bla-bla-bla';
    • Executando uma função sem o parâmetro 'page'.

    Evento de teste Página100


    Iniciando a função criada com o envio da página de evento de teste == 100. Como pode ser visto na captura de tela abaixo, a função funcionou com êxito, retornou o status 200 (OK), bem como uma coleção de coleções que correspondem à centésima página de dados divididos usando paginação.

    Evento de teste de disparo Página100


    Para a pureza do experimento, lançaremos outro evento de teste - “PageBlaBlaBla”. Nesse caso, a função retorna o resultado com o código 415 e um comentário de que é necessário verificar a correção dos parâmetros passados:

    Evento de teste PageBlaBlaBla


    Disparo de evento PageBlaBlaBla



Criação de API


Depois que todos os outros casos são testados e há um entendimento de que a função Lambda funciona conforme o esperado, continuamos a criar a API. Vamos criar um ponto de acesso para a função Lambda criada acima e configurar adicionalmente a proteção contra arranques indesejados usando a Chave da API.

  • Acesse o serviço AWS API Gateway. Clique no botão Criar API, defina o nome da API - getAllBondsList

    Crie uma nova API

  • Adicione o método GET à API recém-criada. Para fazer isso, selecione Ações -> Criar método, selecione o método GET na lista suspensa e clique na marca de seleção

    Novo método GET


    Em seguida, indicamos que o método GET usará nossa função lambda getAllBondsList. Selecione-o e clique no botão Salvar.

    Vinculação de Função Lambda

  • Vamos implantar nossa API, obtendo assim o URL para chamar a API.
    Clique em Ações -> Implementar API e, em seguida, Estágio de Implantação -> Novo Estágio
    É possível implantar a API em diferentes estágios e você pode chamá-los como desejar (por exemplo, DEV / QA / PROD). Vamos implantar imediatamente no PROD.
    Implementar API


    Após a implantação, um link para iniciar a API recém-criada estará disponível. Iremos a este URL na barra de endereços do navegador (ou executaremos o comando curl no terminal) - receberemos uma chamada de API e, como resultado, iniciaremos a função Lambda:

    URL da API


    Usarei o aplicativo Postman para demonstrar o AWS API Gateway. Nele, você pode depurar e testar com bastante facilidade o funcionamento da API.

    Primeiro teste de API
    Copie o URL do estágio PROD para o Postman e envie uma solicitação GET para nossa API:



    Parece que algo deu errado ... a solicitação GET retornou uma resposta JSON com o código 400 e uma dica de que o parâmetro Page não foi definido na solicitação de chamada da API. Adicione suporte para parâmetros de solicitação à API.
  • Suporte para parâmetros passados ​​na solicitação.
    Retornamos às configurações da solicitação GET e vamos para a etapa Solicitação de método.

    Solicitação de método


    Nas configurações detalhadas da Solicitação de método, você precisa expandir o bloco Parâmetros da string de consulta da URL e adicionar um novo parâmetro "página" e torná-lo obrigatório:

    Adicionando um parâmetro


    Retornamos à página Method Execution e vamos para a Solicitação de Integração. Descemos para o final da página e abrimos o bloco "Modelos de mapeamento". Selecione "Quando não houver modelos definidos (recomendado)", no campo Tipo de conteúdo, especifique application / json e clique na marca de seleção. Percorremos a página abaixo e inserimos o código na caixa de texto, conforme indicado na figura abaixo. Depois disso, clique no botão Salvar.

    Solicitação de método


    Após a implantação da API, verificamos novamente, mas com o parâmetro "page" passado:



    É um sucesso! Agora a solicitação deu certo e retornou para nós as coleções contidas na décima página! Viva!
  • Resta apenas proteger nossa API contra ataques indesejados externos.

    Para fazer isso, você precisa configurar a API de maneira que, ao acessar, exija uma chave secreta, que é passada para o cabeçalho.

    Vá para as Chaves da API e crie um novo grupo de chaves da API - KeyForBondsList.

    Chaves de API


    Após a criação da chave da API com sucesso, você deve especificar que a API getAllBondsList deve exigir que a chave da API seja passada no cabeçalho da solicitação. E vincule um KeyForBondsList específico à API getAllBondsList.

    Vamos voltar para as configurações da solicitação GET em Solicitação de método e alterar o parâmetro API Key Required de false para true. Agora a API exigirá a transferência da chave da API.

    Chave de API necessária


    Acesse Plano de uso e crie um novo plano para usar a API.

    Em primeiro lugar, fornecemos um nome e uma descrição e, em segundo lugar, aqui você pode definir limites para iniciar a API, por exemplo, não mais que um lançamento por segundo, etc.

    Criando plano de uso


    Clique em Avançar e vá para a próxima página em que você precisa conectar os estágios da API ao plano de uso:

    Vinculando um estágio a um plano de uso


    Na próxima página, vinculamos as chaves da API ao plano de uso da API. Clique no botão Adicionar chaves de API ao plano de uso e encontre as chaves de API criadas nas etapas anteriores por nome:

    Vinculando chaves da API ao plano de uso


    Depois de executar a implantação e executar a chamada GET da nossa API novamente, obtemos a resposta: "Proibido", porque falta ao cabeçalho da solicitação a chave da API:



    Vamos tentar adicioná-lo, copiando da API Keys -> KeyForBondsList -> API key -> Mostrar e colá-lo na seção correspondente da solicitação com a chave "x-api-key":



    Tudo deu certo! Dessa vez, a solicitação retorna dados sem problemas, a chamada da API é segura e protegida contra invasores pela chave secreta da API.

Conclusões e Resumo


Neste artigo, analisamos a criação de uma API REST auto-escalável sem servidor usando os serviços de nuvem da Amazon. O artigo não era o menor em volume, mas tentei explicar o máximo possível todo o processo de criação da API e compor toda a sequência de ações.

Estou certo de que, após uma ou duas repetições das etapas descritas no artigo, você pode aumentar as APIs da nuvem em 5 minutos ou até mais rápido.

Devido à sua relativa simplicidade, baixo custo e energia, o serviço AWS API Gateway abre grandes oportunidades para os desenvolvedores usarem no trabalho e em projetos comerciais. Para consolidar o material teórico deste artigo, tente fazer uma assinatura anual gratuita do Amazon Web Services e execute as etapas acima para criar uma API REST.

Para qualquer dúvida e sugestão, estou pronto para conversar com prazer. Aguardo seus comentários sobre o artigo e desejo-lhe sucesso!

Source: https://habr.com/ru/post/pt435180/


All Articles