如何使HTTP呼叫到达amazon AWS负载均衡器后面的所有实例?

时间:2016-09-14 19:40:25

标签: amazon-web-services amazon-ec2 elastic-load-balancer

我有一个在Amazon AWS Elastic Load Balancer后面运行的Web应用程序,附加了3个实例。该应用程序有一个/refresh端点来重新加载参考数据。每当有新数据可用时都需要运行,每周发生几次。

我一直在做的是为所有实例分配公共地址,并独立刷新(使用ec2-url/refresh)。我同意Michael's answer on a different topic,ELB背后的EC2实例不允许直接公开访问。现在我的问题是如何让elb-url/refresh调用到达负载均衡器后面的所有实例?

如果我可以从多个实例收集HTTP响应,那就太好了。但我现在不介意盲目刷新。

6 个答案:

答案 0 :(得分:6)

考虑到您的应用程序的限制,这可能是不可能的。值得注意的是,在AWS ELB后面运行的实例的最佳实践应用程序体系结构(特别是如果它们是AutoScalingGroup的一部分)确保实例不是有状态的

我们的想法是通过添加新实例来扩展,或者通过删除实例来扩展,而不会影响数据的完整性或性能。

一种选择是更改应用程序以将参考数据重新加载的结果存储到实例外数据存储中,例如缓存或数据库(例如Elasticache或RDS),而不是内存中。

如果应用程序能够做到这一点,那么您只需要在单个服务器上点击refresh端点 - 它将重新加载参考数据,进行任何分析和操作以有效地存储它适用于应用程序的方法,将其存储到数据存储中,然后所有实例都可以通过共享数据存储访问刷新的数据。

虽然延迟增加会增加数据存储的往返,但对于应用程序的一致性而言通常是值得的 - 在您当前的模型下,如果一个服务器在刷新参考数据方面落后于其他服务器,如果ELB没有使用粘性会话,则通过ELB的请求将返回不一致的数据,具体取决于它们分配给哪个服务器。

答案 1 :(得分:5)

我解决这个问题的方法之一是

  1. 将数据写入AWS s3存储桶
  2. triggering a AWS Lambda function automatically from the s3 write
  3. 使用AWS SDK从Lambda函数中识别附加到ELB的实例,例如使用boto3 from python或AWS Java SDK
  4. 对来自Lambda的个别实例进行调用/刷新
  5. 确保何时创建新实例(由于自动扩展或部署),它在启动期间从s3存储桶中提取数据
  6. 确保实例所在的私有子网允许来自附加到Lambda的子网的流量
  7. 确保附加到实例的安全组允许来自附加到Lambda的安全组的流量
  8. 此解决方案的关键胜利是

    • 从数据写入s3的那一刻起,该过程完全自动化,
    • 避免因自动扩展/部署而导致数据不一致,
    • 易于维护(您不必在任何地方对实例IP地址进行硬编码),
    • 您不必在VPC之外公开实例
    • 高度可用(AWS确保在s3写入时调用Lambda,您不必担心在实例中运行脚本并确保实例启动并运行)

    希望这很有用。

答案 2 :(得分:4)

您无法通过负载均衡器发出这些请求,因此您必须打开实例的安全组,以允许来自ELB以外的来源的传入流量。这并不意味着您需要将其打开到所有直接流量。您可以简单地将安全组中的IP地址列入白名单,以允许来自特定计算机的请求。

如果您不想向这些服务器添加公共IP地址,则需要在VPC内的EC2实例上运行类似curl命令的操作。在这种情况下,您只需要打开安全组以允许来自VPC中存在的某个服务器(或服务器组)的流量。

答案 3 :(得分:1)

在使用S3时,您可以使用S3的ObjectCreated通知自动完成任务。

https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html

https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-notification.html

您可以安装AWS CLI并编写一个简单的Bash脚本来监控该ObjectCreated通知。启动一个Cron作业,该作业将查找用于创建新对象的S3通知。

在该脚本文件中设置条件以卷曲" http://127.0.0.1/refresh"当脚本文件检测到在S3中创建的新对象时,它将卷曲127.0.0.1/refresh,并且您不必每次都手动执行此操作。

答案 4 :(得分:0)

我个人喜欢@redoc的答案,但想为感兴趣的任何人提供另一种选择,这是他和接受的答案的组合。使用SEE对象创建事件,您可以触发一个lambda,但是除了发现实例并调用它们(要求lambda位于vpc中)之外,您还可以让lambda使用SSM(又名Systems Manager)通过Powershell执行命令。或在通过标签定位的EC2实例上使用bash文档。然后,文档将像接受的答案一样调用127.0.0.1/reload。这样做的好处是您的lambda不必位于vpc中,并且您的EC2不需要入站规则来允许来自lambda的流量。缺点是它要求实例安装SSM代理,这听起来比实际工作量还多。已经有使用SSM代理程序进行过优化的AWS AMI,但是您自己将其安装在用户数据中非常简单。根据您的用例,另一个潜在的缺点是它使用指数递增进行同步执行,这意味着如果您要定位20个实例,则它会一次运行1个,然后一次运行2个,然后一次运行4个,然后运行8个,直到它们全部完成,或者达到您为最大设置的值。这是因为它内置了错误恢复功能。如果出现错误,它并不想破坏您的所有内容,例如慢慢将您的体重放在冰上。

答案 5 :(得分:0)

我以不同的方式解决了这个问题,没有在安全组中打开新的流量,也没有求助于S3之类的外部资源。它的灵活性在于它将动态通知通过ECS或ASG添加的实例。

ELB的目标组提供定期运行状况检查的功能,以确保其后面的实例处于活动状态。这是服务器响应的URL。端点可以包括最新配置的时间戳参数。 TG中的每个服务器都将在配置的Interval阈值内收到运行状况检查ping。如果ping的参数更改,则表示刷新。

URL可能类似于: /is-alive?last-configuration=2019-08-27T23%3A50%3A23Z

上面我传递了2019-08-27T23:50:23Z的UTC时间戳

接收请求的服务将检查内存中状态是否至少与timestamp参数一样近。如果不是,它将刷新其状态并更新时间戳。自您的状态刷新以来,下次健康检查将导致无操作。

实施说明

如果刷新状态所花费的时间比间隔窗口或TG健康超时所需的时间长,那么您需要将其卸载到另一个线程中,以防止并发更新或服务完全中断,因为健康检查需要立即返回。否则,该节点将被视为离线。

如果您为此目的使用流量端口,请通过确保无法猜测来确保URL的安全。任何公开暴露的东西都可能遭受DoS攻击。

enter image description here