Usando AWS Lambda funções no Amazon Neptune - Amazon Neptune

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Usando AWS Lambda funções no Amazon Neptune

AWS Lambda as funções têm muitos usos nos aplicativos do Amazon Neptune. Aqui, fornecemos orientações gerais para o uso de funções Lambda com qualquer um dos drivers e variantes de linguagem populares do Gremlin, além de exemplos específicos de funções Lambda escritas em Java e Python. JavaScript

nota

A melhor maneira de usar as funções do Lambda com o Neptune mudou com as versões recentes do mecanismo. O Neptune costumava deixar conexões ociosas abertas muito depois de um contexto de execução do Lambda ter sido reciclado, podendo causar um vazamento de recursos no servidor. Para atenuar isso, costumávamos recomendar abrir e fechar uma conexão com cada invocação do Lambda. A partir da versão 1.0.3.0 do mecanismo, no entanto, o tempo limite da conexão ociosa foi reduzido para que as conexões não vazem mais após a reciclagem de um contexto de execução inativo do Lambda. Por isso, agora recomendamos o uso de uma única conexão durante o contexto de execução. Isso deve incluir algum tratamento de erros e código back-off-and-retry padronizado para lidar com conexões fechadas inesperadamente.

Gerenciando WebSocket conexões Gremlin em funções AWS Lambda

Se você usar uma variante da linguagem Gremlin para consultar Neptune, o driver se conectará ao banco de dados usando uma conexão. WebSocket WebSockets são projetados para suportar cenários de conexão cliente-servidor de longa duração. AWS Lambda, por outro lado, foi projetado para suportar execuções relativamente curtas e apátridas. Essa incompatibilidade na filosofia de design pode causar alguns problemas inesperados ao usar o Lambda para consultar o Neptune.

Uma AWS Lambda função é executada em um contexto de execução que isola a função de outras funções. O contexto de execução é criado na primeira vez que a função é invocada e pode ser reutilizado para invocações subsequentes da mesma função.

No entanto, qualquer contexto de execução nunca é usado para lidar com várias invocações simultâneas da função. Se a função for invocada simultaneamente por vários clientes, o Lambda criará um contexto de execução adicional para cada instância da função. Todos esses novos contextos de execução podem, por sua vez, ser reutilizados para invocações subsequentes da função.

Em algum momento, o Lambda recicla contextos de execução, especialmente se eles estiverem inativos por algum tempo. AWS Lambda expõe o ciclo de vida do contexto de execução, incluindo as Shutdown fases Invoke eInit, por meio de extensões Lambda. Usando essas extensões, você pode escrever um código que limpe recursos externos, como conexões de banco de dados, quando o contexto de execução é reciclado.

Uma prática recomendada comum é abrir a conexão do banco de dados fora da função de manipulador do Lambda para que ela possa ser reutilizada com cada chamada do manipulador. Se a conexão com o banco de dados cair em algum momento, você poderá se reconectar de dentro do manipulador. No entanto, com essa abordagem, existe o perigo de vazamentos de conexão. Se uma conexão ociosa permanecer aberta por muito tempo após a destruição de um contexto de execução, cenários de invocação do Lambda intermitentes poderão gradualmente vazar conexões e esgotar os recursos do banco de dados.

Os limites de conexão e os tempos limite de conexão do Neptune mudaram com as versões mais recentes do mecanismo. Anteriormente, cada instância suportava até 60.000 WebSocket conexões. Agora, o número máximo de WebSocket conexões simultâneas por instância do Neptune varia de acordo com o tipo de instância.

Além disso, a partir da versão 1.0.3.0 do mecanismo, o Neptune reduziu o tempo limite de inatividade das conexões de uma hora para cerca de vinte minutos. Se um cliente não fechar uma conexão, a conexão será fechada automaticamente após um tempo limite de inatividade de 20 a 25 minutos. AWS Lambda não documenta os tempos de vida do contexto de execução, mas experimentos mostram que o novo tempo limite de conexão do Neptune se alinha bem com os tempos limite do contexto de execução inativo do Lambda. No momento em que um contexto de execução inativo é reciclado, há uma boa chance de a conexão já ter sido fechada pelo Neptune ou ser fechada logo depois.

Recomendações para uso AWS Lambda com o Amazon Neptune Gremlin

Agora, recomendamos usar uma única fonte de conexão e percurso de grafos durante toda a vida útil de um contexto de execução do Lambda, em vez de uma para cada invocação de função (cada invocação de função processa somente uma solicitação do cliente). Como as solicitações simultâneas do cliente são tratadas por diferentes instâncias de função executadas em contextos de execução separados, não há necessidade de manter um grupo de conexões para lidar com solicitações simultâneas dentro de uma instância de função. Se o driver do Gremlin que você está usando tiver um grupo de conexões, configure-o para usar apenas uma conexão.

Para lidar com falhas de conexão, use a lógica de repetição em cada consulta. Embora o objetivo seja manter uma única conexão durante a vida útil de um contexto de execução, eventos de rede inesperados podem fazer com que essa conexão seja encerrada abruptamente. Essas falhas de conexão se manifestam como erros diferentes, dependendo do driver que você está usando. É necessário codificar a função do Lambda para lidar com esses problemas de conexão e tentar uma reconexão, se necessário.

Alguns drivers do Gremlin lidam automaticamente com as reconexões. O driver do Java, por exemplo, tenta automaticamente restabelecer a conectividade com o Neptune em nome do código cliente. Com esse driver, o código de função só precisa recuar e repetir a consulta. Os drivers JavaScript e Python, por outro lado, não implementam nenhuma lógica de reconexão automática, portanto, com esses drivers, seu código de função deve tentar se reconectar após recuar e só repetir a consulta depois que a conexão for restabelecida.

Os exemplos de código aqui incluem a lógica de reconexão, em vez de presumir que o cliente esteja cuidando dela.

Recomendações para usar solicitações de gravação do Gremlin no Lambda

Se sua função Lambda modificar dados gráficos, considere adotar uma back-off-and-retry estratégia para lidar com as seguintes exceções:

  • ConcurrentModificationException: a semântica da transação do Neptune significa que as solicitações de gravação às vezes falham com uma ConcurrentModificationException. Nessas situações, experimente um mecanismo de back-off-based repetição exponencial.

  • ReadOnlyViolationException: como a topologia do cluster pode mudar a qualquer momento como resultado de eventos planejados ou não, as responsabilidades de gravação podem migrar de uma instância no cluster para outra. Se o código de função tentar enviar uma solicitação de gravação a uma instância que não seja mais a principal (de gravador), a solicitação falhará com uma ReadOnlyViolationException. Quando isso acontecer, feche a conexão existente, reconecte-se ao endpoint do cluster e repita a solicitação.

Além disso, se você usar uma back-off-and-retry estratégia para lidar com problemas de solicitação de gravação, considere implementar consultas idempotentes para solicitações de criação e atualização (por exemplo, usando fold () .coalesce () .unfold ().

Recomendações para usar solicitações de leitura do Gremlin no Lambda

Se você tiver uma ou mais réplicas de leitura no cluster, é uma boa ideia equilibrar as solicitações de leitura entre essas réplicas. Uma opção é usar o endpoint de leitor. O endpoint de leitor equilibra as conexões entre as réplicas, mesmo que a topologia do cluster mude quando você adiciona ou remove réplicas ou promove uma réplica para se tornar a nova instância principal.

No entanto, o uso do endpoint de leitor pode ocasionar um uso desigual dos recursos do cluster em algumas circunstâncias. O endpoint do leitor funciona alterando periodicamente o host para o qual a DNS entrada aponta. Se um cliente abrir muitas conexões antes da alteração da DNS entrada, todas as solicitações de conexão serão enviadas para uma única instância do Neptune. Esse pode ser o caso de um cenário do Lambda de alto throughput em que um grande número de solicitações simultâneas para a função do Lambda faz com que vários contextos de execução sejam criados, cada um com a própria conexão. Se todas essas conexões forem criadas quase simultaneamente, é provável que todas apontem para a mesma réplica no cluster e permaneçam apontando para essa réplica até que os contextos de execução sejam reciclados.

Uma forma de distribuir solicitações entre instâncias é configurar a função do Lambda para se conectar a um endpoint de instância, escolhido aleatoriamente em uma lista de endpoints de instância de réplica, em vez do endpoint de leitor. A desvantagem dessa abordagem é que ela exige que o código do Lambda manipule as alterações na topologia do cluster, monitorando o cluster e atualizando a lista de endpoints sempre que a associação ao cluster mudar.

Se você estiver escrevendo uma função do Lambda em Java que precise equilibrar as solicitações de leitura entre instâncias no cluster, poderá usar o cliente do Gremlin para Amazon Neptune, um cliente do Gremlin em Java que conhece a topologia do cluster e que distribui de forma justa as conexões e as solicitações em um conjunto de instâncias em um cluster do Neptune. Esta postagem no blog inclui um exemplo de função do Lambda em Java que usa o cliente do Gremlin para Amazon Neptune.

Fatores que podem retardar o início a frio das funções do Lambda em Gremlin no Neptune

A primeira vez que uma AWS Lambda função é invocada é chamada de inicialização a frio. Há vários fatores que podem aumentar a latência de uma inicialização a frio:

  • Atribua memória suficiente à função do Lambda.   — A compilação durante uma inicialização a frio pode ser significativamente mais lenta para uma função Lambda do que seria ativada EC2 porque AWS Lambda aloca CPU ciclos linearmente em proporção à memória que você atribui à função. Com 1.769 MB de memória, uma função recebe o equivalente a um v completo CPU (um v CPU -segundo de créditos por segundo). O impacto de não atribuir memória suficiente para receber CPU ciclos adequados é particularmente pronunciado para grandes funções Lambda escritas em Java.

  • Esteja ciente de que habilitar a autenticação do IAM banco de dados pode retardar uma inicialização a frio — AWS Identity and Access Management (IAM) a autenticação do banco de dados também pode retardar as inicializações a frio, especialmente se a função Lambda precisar gerar uma nova chave de assinatura. Essa latência afeta apenas a inicialização a frio e não as solicitações subsequentes, porque depois que a autenticação do IAM banco de dados estabelece as credenciais de conexão, o Neptune só valida periodicamente se elas ainda são válidas.