如何使NodeJS应用无服务器

希望您像我一样爱Serverless,因为这是同一主题的另一篇文章。

如果它是简单的无服务器REST API,则在AWS:Lambda + API Gateway中的设置非常明显。

但是您的后端可能具有其他(微)服务呢? 您知道,将所有应用程序代码放入一个单一的AWS Lambda函数中并不是最佳方法。

挑战

我们希望将应用程序模块简单地提供为也必须彼此通信的无服务器微服务。 服务之间的通信最好应由一种ACL进行监管。

尝试1. API网关

这是我尝试解决此问题时的第一个想法:只需通过API网关公开所有微服务。 问题是...正在创建的API是公共的。

为什么会有问题呢? 例如,即使访问受到授权限制,我们也不希望在世界任何地方都可以使用计费服务。

好的,您可以将API设为私有,但是安全准则非常有限:

您可以使用API​​网关资源策略来通过以下方式安全地调用您的API:
*特定AWS帐户的用户*指定的源IP地址范围或CIDR块*指定的虚拟私有云(VPC)或VPC终端节点(在任何帐户中)

这使得控制此类服务之间的通信非常困难。 这样做的唯一方法是将服务放在单独的VPC中,这是太多的工作。

实验2. Lambda

我们为什么不将每个微服务放在单独的AWS Lambda中? 这样可以解决问题吗?

是的,它的确是无服务器微服务,您可以使用IAM策略来优化服务间访问。 但是,这并非“容易”。

我知道,如今作为交付部门发挥很小的作用是很正常的。 如果您的服务具有多个端点/方法/功能,则可以将其作为多个lambda提供。

我了解其好处,但您却牺牲了维护和开发的便利性。 另外,我真的不喜欢将服务公开为一组Lambda函数的想法。 想象一下处理计费的几个独立功能? 它不再是一个有限的上下文。 尽管在某些情况下这种粒度可能有用,但这种情况很少见。

尝试3. Fat Lambda

我们是否可以实际上将多个端点作为单个Lambda提供(当然,没有API网关)?

如果可以做到这一点,我们将充分利用先前的选择,但是我们也可以选择部署单元的粒度。

我想看到的是:可以实现的任何服务都应该是带有方法的简单旧JS对象。 通过在对象和AWS Lambda之间添加几行粘合代码,可以很容易地做到这一点。

这是我的实现:aws-rpc。 此nodejs模块在仅传递一个对象的地方公开了lambdaHandler函数,并且该函数自动提供给所有可以访问lambda的用户使用:

从“ aws-rpc”导入{lambdaHandler}; 从'./TestServiceImpl'导入{TestServiceImpl};
//这是您的暂存单元//这是您指定为lambda处理函数的输出export const handler = lambdaHandler(new TestServiceImpl());

现在,您可以简单地将“处理程序”提供为AWS Lambda。 如何调用方法:

从'./TestService'导入{TestService};
const client =等待createClient (“ LambdaName”,“ test”); console.log(等待client.test());

请注意,为了能够为客户端存根对象生成方法,您必须像示例中一样将所有方法名称传递给createClient。

这是必需的,因为JS在TypeScript接口上没有运行时信息。 我可以用抽象类来实现它,但是我不喜欢\ \ _(ツ)_ /¯。

奖金! 您可以在本地完成所有操作!

我认为让您的本地开发环境尽可能舒适是非常重要的。 因此,我还添加了在本地运行服务和客户端的功能,而无需为AWS提供任何功能(请参阅功能runService和createClient)。 您可以在GitHub存储库中找到示例。

概要

当您迷失了云提供商提供的服务并彻底检查基础架构时,这很容易做到。

我总是选择我能想到的最简单,最明确的解决方案。 此外,请始终牢记可以从其他平台重用许多技术和实践(粗体NodeJS Lambda的思想受到Java世界中所谓的粗体眼镜的启发)。

如果您喜欢此主题,请阅读以下内容:

  • 您需要学习如何构建最佳的无服务器架构
  • 如何建立免费的无服务器CI / CD管道:3个简单示例
  • 跨区域轻松复制DynamoDB
  • 如何构建多区域应用程序(零支付)
  • 使Java Web App无服务器

评论,喜欢和分享非常感激。 自下而上!