亚马逊AWS官方博客

适合无服务器应用程序的 AWS Cloud Map 服务发现

基于微服务的架构有助于降低应用程序组件的复杂性,但同时也会带来与微服务之间的连接性相关的新问题。跨多个阶段和部署跟踪所有应用程序组件(无论是定制的还是托管的 AWS 服务)是一项艰巨的任务。AWS Cloud Map 是一个用于所有云资源和应用程序组件的完全托管的服务发现工具,可帮助您的应用程序连接到正确的终端节点,从而使您的部署更安全,并降低基础设施代码的复杂性。在 Peak.ai 技术架构师 Ewan Valentine 的这篇客座博文中,我们将介绍一个开源库,该库可让您无缝地将 AWS Cloud Map 服务发现集成到您的无服务器应用程序中,从而使向基于微服务架构的大规模过渡更加平滑。

Alexandr Moroz

 

大约一年前,在 Peak.ai,我们开始了向基于微服务的无服务器架构转变的过程。我们面临的关键问题之一是选择正确的服务发现工具。在 AWS Cloud Map 推出之前,我们已经开始了自己尝试。我们使用过很多工具:Consul、etcd、ZooKeeper 等,但所有这些工具在设置和持续维护方面都有相当大的开销。

作为负责此任务的五人小团队,我们选择了托管的解决方案。对我们来说幸运的是,AWS 推出了 AWS Cloud Map,这正是我们所需要的。这个工具的设置非常简单明了,我们能够在 AWS Cloud Map 工具之上快速创建一套丰富的工具,以便我们可以注册整个生态系统中的服务并与之交互,将服务彼此紧密地耦合在一起,而无需硬编码或传递 ARN。我们现已开源这些工具,以便其他 AWS Cloud Map 客户可以受益。

AWS Cloud Map 功能

以下列表并不详尽,但却是对我们最关键的 AWS Cloud Map 功能:

服务支持

AWS Cloud Map 开箱即用地支持许多主要的 AWS 服务:您可以创建对 SQS,DynamoDB 表以及 S3 存储桶等的 DNS 可发现引用。

DNS、API 或两者

AWS Cloud Map 支持为您的服务、表或存储桶创建 DNS 友好的 url,但是您也可以使用 API 发现类型,从而可以使用 AWS SDK 按元数据发现实例。这对于不一定需要通过 URL 到达的服务非常有用。例如,如果您有很多通过直接调用或 SQS 队列进行通信的 Lambda 微服务,则可以简单地为每个服务发现 ARN,然后使用 AWS SDK 调用已发现的服务。我们还编写了一个封套,根据发出的调用类型来抽象围绕 AWS SDK 的调用行为。我们将在后文深入探讨。您还可以创建名称空间,使您可以同时使用 http 和 API 进行发现。

本质无服务器

通常,在使用服务发现时,您会发现自己必须维护并运行服务发现软件的实例,例如 EC2 实例上的 etcd 或 consul。您必须关注规模、安全性、物理资源等。借助 AWS Cloud Map,所有这些您都可以托管,因此可以专注于编写业务逻辑。

易于使用

AWS Cloud Map 非常容易上手和使用。例如,您可以调用 discoverInstances({ NamespaceName, ServiceName: QueryParameters }),它会返回您服务注册实例的列表,例如 lambda 函数。

健康检查

AWS Cloud Map 支持检查服务的健康状况,这意味着您可以编写更具弹性的系统,以检查您尝试调用的服务是否健康且可访问。这也意味着您可以编写意外处理(例如指数退避),并安全地捕获故障。

安全升级

由于 AWS Cloud Map 充当其他服务的目录或门面,因此您可以通过更新该服务的 Cloud Map 服务/实例来安全地关闭服务。例如,这意味着您可以部署、升级和维护服务,而不必在其他地方更新对它们的引用。

定价

在无服务器方法中,您需要为使用量付费:每百万个请求 1 USD。API 注册是免费的,向 DNS 注册的每个资源则要支付 0.10 USD。对我们来说这意味着使用 AWS Cloud Map 比运行自己工具的要经济得多。

我们的应用程序用例

为了将 AWS Cloud Map 集成到我们的项目中,我们在 AWS Cloud Map SDK 的基础上编写了一个薄封套,以执行服务发现:

const job = await Discovery.request(‘ais.scheduler->get-job’, {
  id,
  type,
});

// Trigger a lambda via SNS
await Discovery.publish(‘ais.my-event’, event);

// Queue a message in SQS
await Discover.queue(‘ais.my-queue’, message);

// Listen on an SQS queue
const eventEmitter = await Discover.listen(‘ais.my-queue’);

AWS Cloud Map 在应用程序和 DNS 级别都支持服务发现,因此您可以为服务创建友好的 URL,这对于容器化应用程序或通常需要由其他服务来解决的负载均衡器的应用程序非常有用。

注册您的服务

创建我们的 AWS CloudFormation 模板时,我们只是针对用户友好的名称注册了我们服务的 ARN,例如:

CloudMapService:
    Type: 'AWS::ServiceDiscovery::Service'
    Properties:
      Description: discover handlers for scheduler
      Name: scheduler-service
      NamespaceId: !FindInMap [ CloudMapMappings, !Ref Stage, CloudMapNamespaceID ]

  SchedulerQueueInstance:
    Type: 'AWS::ServiceDiscovery::Instance'
    Properties:
      InstanceAttributes:
        arn: !Join [ '-', [ 'ais', !Ref Stage, scheduler.fifo' ] ]
        type: queue
        url: !Ref SchedulerQueue
      InstanceId: scheduler-queue
      ServiceId: !Ref CloudMapService

然后在我们代码中,无论平台内的任何地方,我们都可以使用我们的库来引用该队列:

await ServiceDiscovery.queue(‘namespace-prod.scheduler-service->scheduler-queue’, message);

我们创建了一个包含以下三个部分的标准格式:

<namespace>.<service>-><instance>

无服务器集成

在 Peak,我们大量使用无服务器框架,因此我们想研究将 AWS Cloud Map 集成到无服务器框架工作流程的方法。我们还为 AWS Cloud Map 创建了一个无服务器插件和一个无服务器组件,它们现在已添加到官方的无服务器插件存储库中,因此您可以使用无服务器框架直接将您的无服务器微服务注册并集成到 AWS Cloud Map 中。

小结

AWS Cloud Map 可充当胶水,大规模地绑定我们的所有业务逻辑,从而使我们能够迈入微服务平台。AWS Cloud Map 使我们能够在推出新功能甚至替换旧功能时更快地行动。AWS Cloud Map 的简易特性意味着它可以快速实施,并且易于获取和采用。

我们希望您能参与其中并尝试我们基于 AWS Cloud Map 的库:

我们欢迎各种想法和建议,也希望看到大家一起尝试!

Ewan Valentine.

Ewan Valentine

Ewan Valentine 是 Peak.ai 的技术架构师和常驻 Gopher,专注于微服务和 AI 解决方案。早前就职于 BBC、LAD Bible 和 Boots Walgreens。

本博文中的内容和意见属于第三方作者,AWS 不对本博文的内容或准确性负责。