

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 AWS Lambda 与 Amazon Neptune Gremlin 结合使用的建议
<a name="lambda-functions-gremlin-recommendations"></a>

现在，我们建议在 Lambda 执行上下文的整个生命周期内使用单个连接和图形遍历源，而不是为每个函数调用使用一个连接和图形遍历源（每个函数调用仅处理一个客户端请求）。由于并发客户端请求是由在不同执行上下文中运行的不同函数实例处理的，因此无需维护连接池来处理函数实例内的并发请求。如果您使用的 Gremlin 驱动程序有连接池，请将其配置为仅使用一个连接。

要处理连接失败，请围绕每个查询使用重试逻辑。尽管目标是在执行上下文的生命周期内保持单个连接，但意外的网络事件可能会导致该连接突然终止。此类连接失败表现为不同的错误，具体取决于您使用的驱动程序。您应该对 Lambda 函数进行编码，以处理这些连接问题，并在必要时尝试重新连接。

某些 Gremlin 驱动程序会自动处理重新连接。例如，Java 驱动程序会自动尝试代表您的客户端代码重新建立与 Neptune 的连接。使用此驱动程序，您的函数代码只需要退出并重试查询即可。相比之下，JavaScript 和 Python 驱动程序不实现任何自动重新连接逻辑，因此使用这些驱动程序，您的函数代码必须在回退后尝试重新连接，并且只有在重新建立连接后才会重试查询。

这里的代码示例确实包括重新连接逻辑，而不是假设客户端正在处理它。

# 在 Lambda 中使用 Gremlin 写入请求的建议
<a name="lambda-functions-gremlin-write-recommendations"></a>

如果您的 Lambda 函数修改了图形数据，请考虑采用回退并重试策略来处理以下异常：
+ **`ConcurrentModificationException`** – Neptune 事务语义意味着写入请求有时会失败并引发 `ConcurrentModificationException`。在这些情况下，请尝试使用基于指数回退的重试机制。
+ **`ReadOnlyViolationException`** – 由于计划内或计划外的事件会导致集群拓扑随时可能发生变化，因此，写入职责可能会从集群中的一个实例迁移到另一个实例。如果您的函数代码尝试向不再是主（写入器）实例的实例发送写入请求，则请求将失败并引发 `ReadOnlyViolationException`。发生这种情况时，请关闭现有连接，重新连接到集群端点，然后重试请求。

另外，如果您使用回退并重试策略来处理写入请求问题，请考虑为创建和更新请求实现幂等性查询（例如，使用 [fold().coalesce().unfold()](http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html#upsert)）。

# 在 Lambda 中使用 Gremlin 读取请求的建议
<a name="lambda-functions-gremlin-read-recommendations"></a>

如果您的集群中有一个或多个只读副本，则最好在这些副本之间平衡读取请求。一种选择是使用[读取器端点](feature-overview-endpoints.md)。即使在您添加或删除副本或将副本提升为新的主实例时，集群拓扑发生了变化，读取器端点也会平衡副本间的连接。

但是，在某些情况下，使用读取器端点可能会导致集群资源的使用不均衡。读取器端点的工作方式是定期更改 DNS 条目指向的主机。如果客户端在 DNS 条目更改之前打开了大量连接，则所有连接请求都将发送到单个 Neptune 实例。高吞吐量 Lambda 场景可能就是这种情况，在这种场景中，对 Lambda 函数的大量并发请求会导致创建多个执行上下文，每个上下文都有自己的连接。如果这些连接几乎同时创建，则这些连接很可能都指向集群中的同一个副本，并且一直指向该副本，直到执行上下文被回收为止。

跨实例分配请求的一种方法是将 Lambda 函数配置为连接到从副本实例端点列表中随机选择的实例端点，而不是读取器端点。这种方法的缺点是，它要求 Lambda 代码通过监控集群并在集群成员资格发生变化时更新端点列表，来处理集群拓扑的变化。

如果您正在编写需要在集群中的实例之间平衡读取请求的 Java Lambda 函数，则可以使用[适用于 Amazon Neptune 的 Gremlin 客户端](https://github.com/aws/neptune-gremlin-client)，这是一款 Java Gremlin 客户端，它知道您的集群拓扑，可以公平地在 Neptune 集群中的一组实例间分配连接和请求。[这篇博客文章](https://aws.amazon.com/blogs/database/load-balance-graph-queries-using-the-amazon-neptune-gremlin-client/)包括一个使用适用于 Amazon Neptune 的 Gremlin 客户端的 Java Lambda 函数示例。

# 可能减慢 Neptune Gremlin Lambda 函数冷启动速度的因素
<a name="lambda-functions-gremlin-cold-start-recommendations"></a>

第一次调用 AWS Lambda 函数称为冷启动。有几个因素会增加冷启动的延迟：
+ **请务必为您的 Lambda 函数分配足够的内存。**  – Lambda 函数在冷启动期间的编译速度可能比在 EC2 上慢得多，因为 AWS Lambda 按您分配给该函数的[内存成比例线性](https://docs.aws.amazon.com/lambda/latest/dg/configuration-console.html)分配 CPU 周期。在内存为 1769 MB 时，函数收到相当于 1 个完整 vCPU（每秒一个 vCPU 秒的积分）的处理能力。对于用 Java 编写的大型 Lambda 函数，未分配足够的内存来接收足够的 CPU 周期的影响尤其明显。
+ **请注意，[启用 IAM 数据库身份验证](iam-auth-enable.md)可能会减慢冷启动速度** – AWS Identity and Access Management (IAM) 数据库身份验证还会减慢冷启动速度，尤其是在 Lambda 函数必须生成新的签名密钥的情况下。这种延迟仅影响冷启动，而不影响后续请求，因为一旦 IAM 数据库身份验证建立了连接凭证，Neptune 只会定期验证这些凭证是否仍然有效。

  