使用 SDK for Java 2.x 的 Auto Scaling 示例 - AWS SDK for Java 2.x

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

使用 SDK for Java 2.x 的 Auto Scaling 示例

以下代码示例向您展示了如何使用与 Auto Scaling AWS SDK for Java 2.x 配合使用来执行操作和实现常见场景。

操作是大型程序的代码摘录,必须在上下文中运行。您可以通过操作了解如何调用单个服务函数,还可以通过函数相关场景和跨服务示例的上下文查看操作。

场景 是展示如何通过在同一服务中调用多个函数来完成特定任务的代码示例。

每个示例都包含一个指向的链接 GitHub,您可以在其中找到有关如何在上下文中设置和运行代码的说明。

开始使用

以下代码示例演示了如何开始使用 Auto Scaling。

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.autoscaling.AutoScalingClient; import software.amazon.awssdk.services.autoscaling.model.AutoScalingGroup; import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingGroupsResponse; import java.util.List; /** * Before running this SDK for Java (v2) code example, set up your development * environment, including your credentials. * * For more information, see the following documentation: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class DescribeAutoScalingGroups { public static void main(String[] args) throws InterruptedException { AutoScalingClient autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); describeGroups(autoScalingClient); } public static void describeGroups(AutoScalingClient autoScalingClient) { DescribeAutoScalingGroupsResponse response = autoScalingClient.describeAutoScalingGroups(); List<AutoScalingGroup> groups = response.autoScalingGroups(); groups.forEach(group -> { System.out.println("Group Name: " + group.autoScalingGroupName()); System.out.println("Group ARN: " + group.autoScalingGroupARN()); }); } }

操作

以下代码示例演示了如何使用 CreateAutoScalingGroup

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

import software.amazon.awssdk.core.waiters.WaiterResponse; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.autoscaling.AutoScalingClient; import software.amazon.awssdk.services.autoscaling.model.AutoScalingException; import software.amazon.awssdk.services.autoscaling.model.CreateAutoScalingGroupRequest; import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingGroupsRequest; import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingGroupsResponse; import software.amazon.awssdk.services.autoscaling.model.LaunchTemplateSpecification; import software.amazon.awssdk.services.autoscaling.waiters.AutoScalingWaiter; /** * Before running this SDK for Java (v2) code example, set up your development * environment, including your credentials. * * For more information, see the following documentation: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class CreateAutoScalingGroup { public static void main(String[] args) { final String usage = """ Usage: <groupName> <launchTemplateName> <serviceLinkedRoleARN> <vpcZoneId> Where: groupName - The name of the Auto Scaling group. launchTemplateName - The name of the launch template.\s vpcZoneId - A subnet Id for a virtual private cloud (VPC) where instances in the Auto Scaling group can be created. """; if (args.length != 3) { System.out.println(usage); System.exit(1); } String groupName = args[0]; String launchTemplateName = args[1]; String vpcZoneId = args[2]; AutoScalingClient autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); createAutoScalingGroup(autoScalingClient, groupName, launchTemplateName, vpcZoneId); autoScalingClient.close(); } public static void createAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName, String launchTemplateName, String vpcZoneId) { try { AutoScalingWaiter waiter = autoScalingClient.waiter(); LaunchTemplateSpecification templateSpecification = LaunchTemplateSpecification.builder() .launchTemplateName(launchTemplateName) .build(); CreateAutoScalingGroupRequest request = CreateAutoScalingGroupRequest.builder() .autoScalingGroupName(groupName) .availabilityZones("us-east-1a") .launchTemplate(templateSpecification) .maxSize(1) .minSize(1) .vpcZoneIdentifier(vpcZoneId) .build(); autoScalingClient.createAutoScalingGroup(request); DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); WaiterResponse<DescribeAutoScalingGroupsResponse> waiterResponse = waiter .waitUntilGroupExists(groupsRequest); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("Auto Scaling Group created"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } }

以下代码示例演示了如何使用 DeleteAutoScalingGroup

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.autoscaling.AutoScalingClient; import software.amazon.awssdk.services.autoscaling.model.AutoScalingException; import software.amazon.awssdk.services.autoscaling.model.DeleteAutoScalingGroupRequest; /** * Before running this SDK for Java (v2) code example, set up your development * environment, including your credentials. * * For more information, see the following documentation: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class DeleteAutoScalingGroup { public static void main(String[] args) { final String usage = """ Usage: <groupName> Where: groupName - The name of the Auto Scaling group. """; if (args.length != 1) { System.out.println(usage); System.exit(1); } String groupName = args[0]; AutoScalingClient autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); deleteAutoScalingGroup(autoScalingClient, groupName); autoScalingClient.close(); } public static void deleteAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName) { try { DeleteAutoScalingGroupRequest deleteAutoScalingGroupRequest = DeleteAutoScalingGroupRequest.builder() .autoScalingGroupName(groupName) .forceDelete(true) .build(); autoScalingClient.deleteAutoScalingGroup(deleteAutoScalingGroupRequest); System.out.println("You successfully deleted " + groupName); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } }

以下代码示例演示了如何使用 DescribeAutoScalingGroups

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.autoscaling.AutoScalingClient; import software.amazon.awssdk.services.autoscaling.model.AutoScalingException; import software.amazon.awssdk.services.autoscaling.model.AutoScalingGroup; import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingGroupsResponse; import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingGroupsRequest; import software.amazon.awssdk.services.autoscaling.model.Instance; import java.util.List; /** * Before running this SDK for Java (v2) code example, set up your development * environment, including your credentials. * * For more information, see the following documentation: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class DescribeAutoScalingInstances { public static void main(String[] args) { final String usage = """ Usage: <groupName> Where: groupName - The name of the Auto Scaling group. """; if (args.length != 1) { System.out.println(usage); System.exit(1); } String groupName = args[0]; AutoScalingClient autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); String instanceId = getAutoScaling(autoScalingClient, groupName); System.out.println(instanceId); autoScalingClient.close(); } public static String getAutoScaling(AutoScalingClient autoScalingClient, String groupName) { try { String instanceId = ""; DescribeAutoScalingGroupsRequest scalingGroupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); DescribeAutoScalingGroupsResponse response = autoScalingClient .describeAutoScalingGroups(scalingGroupsRequest); List<AutoScalingGroup> groups = response.autoScalingGroups(); for (AutoScalingGroup group : groups) { System.out.println("The group name is " + group.autoScalingGroupName()); System.out.println("The group ARN is " + group.autoScalingGroupARN()); List<Instance> instances = group.instances(); for (Instance instance : instances) { instanceId = instance.instanceId(); } } return instanceId; } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } return ""; } }

以下代码示例演示了如何使用 DescribeAutoScalingInstances

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void describeAutoScalingInstance(AutoScalingClient autoScalingClient, String id) { try { DescribeAutoScalingInstancesRequest describeAutoScalingInstancesRequest = DescribeAutoScalingInstancesRequest .builder() .instanceIds(id) .build(); DescribeAutoScalingInstancesResponse response = autoScalingClient .describeAutoScalingInstances(describeAutoScalingInstancesRequest); List<AutoScalingInstanceDetails> instances = response.autoScalingInstances(); for (AutoScalingInstanceDetails instance : instances) { System.out.println("The instance lifecycle state is: " + instance.lifecycleState()); } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

以下代码示例演示了如何使用 DescribeScalingActivities

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void describeScalingActivities(AutoScalingClient autoScalingClient, String groupName) { try { DescribeScalingActivitiesRequest scalingActivitiesRequest = DescribeScalingActivitiesRequest.builder() .autoScalingGroupName(groupName) .maxRecords(10) .build(); DescribeScalingActivitiesResponse response = autoScalingClient .describeScalingActivities(scalingActivitiesRequest); List<Activity> activities = response.activities(); for (Activity activity : activities) { System.out.println("The activity Id is " + activity.activityId()); System.out.println("The activity details are " + activity.details()); } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

以下代码示例演示了如何使用 DisableMetricsCollection

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void disableMetricsCollection(AutoScalingClient autoScalingClient, String groupName) { try { DisableMetricsCollectionRequest disableMetricsCollectionRequest = DisableMetricsCollectionRequest.builder() .autoScalingGroupName(groupName) .metrics("GroupMaxSize") .build(); autoScalingClient.disableMetricsCollection(disableMetricsCollectionRequest); System.out.println("The disable metrics collection operation was successful"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

以下代码示例演示了如何使用 EnableMetricsCollection

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void enableMetricsCollection(AutoScalingClient autoScalingClient, String groupName) { try { EnableMetricsCollectionRequest collectionRequest = EnableMetricsCollectionRequest.builder() .autoScalingGroupName(groupName) .metrics("GroupMaxSize") .granularity("1Minute") .build(); autoScalingClient.enableMetricsCollection(collectionRequest); System.out.println("The enable metrics collection operation was successful"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

以下代码示例演示了如何使用 SetDesiredCapacity

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void setDesiredCapacity(AutoScalingClient autoScalingClient, String groupName) { try { SetDesiredCapacityRequest capacityRequest = SetDesiredCapacityRequest.builder() .autoScalingGroupName(groupName) .desiredCapacity(2) .build(); autoScalingClient.setDesiredCapacity(capacityRequest); System.out.println("You have set the DesiredCapacity to 2"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }
  • 有关 API 的详细信息,请参阅 AWS SDK for Java 2.x API 参考SetDesiredCapacity中的。

以下代码示例演示了如何使用 TerminateInstanceInAutoScalingGroup

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void terminateInstanceInAutoScalingGroup(AutoScalingClient autoScalingClient, String instanceId) { try { TerminateInstanceInAutoScalingGroupRequest request = TerminateInstanceInAutoScalingGroupRequest.builder() .instanceId(instanceId) .shouldDecrementDesiredCapacity(false) .build(); autoScalingClient.terminateInstanceInAutoScalingGroup(request); System.out.println("You have terminated instance " + instanceId); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

以下代码示例演示了如何使用 UpdateAutoScalingGroup

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static void updateAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName, String launchTemplateName) { try { AutoScalingWaiter waiter = autoScalingClient.waiter(); LaunchTemplateSpecification templateSpecification = LaunchTemplateSpecification.builder() .launchTemplateName(launchTemplateName) .build(); UpdateAutoScalingGroupRequest groupRequest = UpdateAutoScalingGroupRequest.builder() .maxSize(3) .autoScalingGroupName(groupName) .launchTemplate(templateSpecification) .build(); autoScalingClient.updateAutoScalingGroup(groupRequest); DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); WaiterResponse<DescribeAutoScalingGroupsResponse> waiterResponse = waiter .waitUntilGroupInService(groupsRequest); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("You successfully updated the auto scaling group " + groupName); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

场景

以下代码示例演示了如何创建可返回书籍、电影和歌曲推荐的负载均衡的 Web 服务。该示例演示服务如何响应故障,以及如何重组服务以提高故障发生时的弹性。

  • 使用 Amazon EC2 Auto Scaling 组根据启动模板创建 Amazon Elastic Compute Cloud(Amazon EC2)实例,并将实例数量保持在指定范围内。

  • 使用弹性负载均衡处理和分发 HTTP 请求。

  • 监控自动扩缩组中实例的运行状况,并仅将请求转发到运行状况良好的实例。

  • 在每个 EC2 实例上运行 Python Web 服务器以处理 HTTP 请求。Web 服务器以建议和运行状况检查作为响应。

  • 使用 Amazon DynamoDB 表模拟推荐服务。

  • 通过更新 AWS Systems Manager 参数来控制 Web 服务器对请求和运行状况检查的响应。

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

在命令提示符中运行交互式场景。

public class Main { public static final String fileName = "C:\\AWS\\resworkflow\\recommendations.json"; // Modify file location. public static final String tableName = "doc-example-recommendation-service"; public static final String startScript = "C:\\AWS\\resworkflow\\server_startup_script.sh"; // Modify file location. public static final String policyFile = "C:\\AWS\\resworkflow\\instance_policy.json"; // Modify file location. public static final String ssmJSON = "C:\\AWS\\resworkflow\\ssm_only_policy.json"; // Modify file location. public static final String failureResponse = "doc-example-resilient-architecture-failure-response"; public static final String healthCheck = "doc-example-resilient-architecture-health-check"; public static final String templateName = "doc-example-resilience-template"; public static final String roleName = "doc-example-resilience-role"; public static final String policyName = "doc-example-resilience-pol"; public static final String profileName = "doc-example-resilience-prof"; public static final String badCredsProfileName = "doc-example-resilience-prof-bc"; public static final String targetGroupName = "doc-example-resilience-tg"; public static final String autoScalingGroupName = "doc-example-resilience-group"; public static final String lbName = "doc-example-resilience-lb"; public static final String protocol = "HTTP"; public static final int port = 80; public static final String DASHES = new String(new char[80]).replace("\0", "-"); public static void main(String[] args) throws IOException, InterruptedException { Scanner in = new Scanner(System.in); Database database = new Database(); AutoScaler autoScaler = new AutoScaler(); LoadBalancer loadBalancer = new LoadBalancer(); System.out.println(DASHES); System.out.println("Welcome to the demonstration of How to Build and Manage a Resilient Service!"); System.out.println(DASHES); System.out.println(DASHES); System.out.println("A - SETUP THE RESOURCES"); System.out.println("Press Enter when you're ready to start deploying resources."); in.nextLine(); deploy(loadBalancer); System.out.println(DASHES); System.out.println(DASHES); System.out.println("B - DEMO THE RESILIENCE FUNCTIONALITY"); System.out.println("Press Enter when you're ready."); in.nextLine(); demo(loadBalancer); System.out.println(DASHES); System.out.println(DASHES); System.out.println("C - DELETE THE RESOURCES"); System.out.println(""" This concludes the demo of how to build and manage a resilient service. To keep things tidy and to avoid unwanted charges on your account, we can clean up all AWS resources that were created for this demo. """); System.out.println("\n Do you want to delete the resources (y/n)? "); String userInput = in.nextLine().trim().toLowerCase(); // Capture user input if (userInput.equals("y")) { // Delete resources here deleteResources(loadBalancer, autoScaler, database); System.out.println("Resources deleted."); } else { System.out.println(""" Okay, we'll leave the resources intact. Don't forget to delete them when you're done with them or you might incur unexpected charges. """); } System.out.println(DASHES); System.out.println(DASHES); System.out.println("The example has completed. "); System.out.println("\n Thanks for watching!"); System.out.println(DASHES); } // Deletes the AWS resources used in this example. private static void deleteResources(LoadBalancer loadBalancer, AutoScaler autoScaler, Database database) throws IOException, InterruptedException { loadBalancer.deleteLoadBalancer(lbName); System.out.println("*** Wait 30 secs for resource to be deleted"); TimeUnit.SECONDS.sleep(30); loadBalancer.deleteTargetGroup(targetGroupName); autoScaler.deleteAutoScaleGroup(autoScalingGroupName); autoScaler.deleteRolesPolicies(policyName, roleName, profileName); autoScaler.deleteTemplate(templateName); database.deleteTable(tableName); } private static void deploy(LoadBalancer loadBalancer) throws InterruptedException, IOException { Scanner in = new Scanner(System.in); System.out.println( """ For this demo, we'll use the AWS SDK for Java (v2) to create several AWS resources to set up a load-balanced web service endpoint and explore some ways to make it resilient against various kinds of failures. Some of the resources create by this demo are: \t* A DynamoDB table that the web service depends on to provide book, movie, and song recommendations. \t* An EC2 launch template that defines EC2 instances that each contain a Python web server. \t* An EC2 Auto Scaling group that manages EC2 instances across several Availability Zones. \t* An Elastic Load Balancing (ELB) load balancer that targets the Auto Scaling group to distribute requests. """); System.out.println("Press Enter when you're ready."); in.nextLine(); System.out.println(DASHES); System.out.println(DASHES); System.out.println("Creating and populating a DynamoDB table named " + tableName); Database database = new Database(); database.createTable(tableName, fileName); System.out.println(DASHES); System.out.println(DASHES); System.out.println(""" Creating an EC2 launch template that runs '{startup_script}' when an instance starts. This script starts a Python web server defined in the `server.py` script. The web server listens to HTTP requests on port 80 and responds to requests to '/' and to '/healthcheck'. For demo purposes, this server is run as the root user. In production, the best practice is to run a web server, such as Apache, with least-privileged credentials. The template also defines an IAM policy that each instance uses to assume a role that grants permissions to access the DynamoDB recommendation table and Systems Manager parameters that control the flow of the demo. """); LaunchTemplateCreator templateCreator = new LaunchTemplateCreator(); templateCreator.createTemplate(policyFile, policyName, profileName, startScript, templateName, roleName); System.out.println(DASHES); System.out.println(DASHES); System.out.println( "Creating an EC2 Auto Scaling group that maintains three EC2 instances, each in a different Availability Zone."); System.out.println("*** Wait 30 secs for the VPC to be created"); TimeUnit.SECONDS.sleep(30); AutoScaler autoScaler = new AutoScaler(); String[] zones = autoScaler.createGroup(3, templateName, autoScalingGroupName); System.out.println(""" At this point, you have EC2 instances created. Once each instance starts, it listens for HTTP requests. You can see these instances in the console or continue with the demo. Press Enter when you're ready to continue. """); in.nextLine(); System.out.println(DASHES); System.out.println(DASHES); System.out.println("Creating variables that control the flow of the demo."); ParameterHelper paramHelper = new ParameterHelper(); paramHelper.reset(); System.out.println(DASHES); System.out.println(DASHES); System.out.println(""" Creating an Elastic Load Balancing target group and load balancer. The target group defines how the load balancer connects to instances. The load balancer provides a single endpoint where clients connect and dispatches requests to instances in the group. """); String vpcId = autoScaler.getDefaultVPC(); List<Subnet> subnets = autoScaler.getSubnets(vpcId, zones); System.out.println("You have retrieved a list with " + subnets.size() + " subnets"); String targetGroupArn = loadBalancer.createTargetGroup(protocol, port, vpcId, targetGroupName); String elbDnsName = loadBalancer.createLoadBalancer(subnets, targetGroupArn, lbName, port, protocol); autoScaler.attachLoadBalancerTargetGroup(autoScalingGroupName, targetGroupArn); System.out.println("Verifying access to the load balancer endpoint..."); boolean wasSuccessul = loadBalancer.verifyLoadBalancerEndpoint(elbDnsName); if (!wasSuccessul) { System.out.println("Couldn't connect to the load balancer, verifying that the port is open..."); CloseableHttpClient httpClient = HttpClients.createDefault(); // Create an HTTP GET request to "http://checkip.amazonaws.com" HttpGet httpGet = new HttpGet("http://checkip.amazonaws.com"); try { // Execute the request and get the response HttpResponse response = httpClient.execute(httpGet); // Read the response content. String ipAddress = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8).trim(); // Print the public IP address. System.out.println("Public IP Address: " + ipAddress); GroupInfo groupInfo = autoScaler.verifyInboundPort(vpcId, port, ipAddress); if (!groupInfo.isPortOpen()) { System.out.println(""" For this example to work, the default security group for your default VPC must allow access from this computer. You can either add it automatically from this example or add it yourself using the AWS Management Console. """); System.out.println( "Do you want to add a rule to security group " + groupInfo.getGroupName() + " to allow"); System.out.println("inbound traffic on port " + port + " from your computer's IP address (y/n) "); String ans = in.nextLine(); if ("y".equalsIgnoreCase(ans)) { autoScaler.openInboundPort(groupInfo.getGroupName(), String.valueOf(port), ipAddress); System.out.println("Security group rule added."); } else { System.out.println("No security group rule added."); } } } catch (AutoScalingException e) { e.printStackTrace(); } } else if (wasSuccessul) { System.out.println("Your load balancer is ready. You can access it by browsing to:"); System.out.println("\t http://" + elbDnsName); } else { System.out.println("Couldn't get a successful response from the load balancer endpoint. Troubleshoot by"); System.out.println("manually verifying that your VPC and security group are configured correctly and that"); System.out.println("you can successfully make a GET request to the load balancer."); } System.out.println("Press Enter when you're ready to continue with the demo."); in.nextLine(); } // A method that controls the demo part of the Java program. public static void demo(LoadBalancer loadBalancer) throws IOException, InterruptedException { ParameterHelper paramHelper = new ParameterHelper(); System.out.println("Read the ssm_only_policy.json file"); String ssmOnlyPolicy = readFileAsString(ssmJSON); System.out.println("Resetting parameters to starting values for demo."); paramHelper.reset(); System.out.println( """ This part of the demonstration shows how to toggle different parts of the system to create situations where the web service fails, and shows how using a resilient architecture can keep the web service running in spite of these failures. At the start, the load balancer endpoint returns recommendations and reports that all targets are healthy. """); demoChoices(loadBalancer); System.out.println( """ The web service running on the EC2 instances gets recommendations by querying a DynamoDB table. The table name is contained in a Systems Manager parameter named self.param_helper.table. To simulate a failure of the recommendation service, let's set this parameter to name a non-existent table. """); paramHelper.put(paramHelper.tableName, "this-is-not-a-table"); System.out.println( """ \nNow, sending a GET request to the load balancer endpoint returns a failure code. But, the service reports as healthy to the load balancer because shallow health checks don't check for failure of the recommendation service. """); demoChoices(loadBalancer); System.out.println( """ Instead of failing when the recommendation service fails, the web service can return a static response. While this is not a perfect solution, it presents the customer with a somewhat better experience than failure. """); paramHelper.put(paramHelper.failureResponse, "static"); System.out.println(""" Now, sending a GET request to the load balancer endpoint returns a static response. The service still reports as healthy because health checks are still shallow. """); demoChoices(loadBalancer); System.out.println("Let's reinstate the recommendation service."); paramHelper.put(paramHelper.tableName, paramHelper.dyntable); System.out.println(""" Let's also substitute bad credentials for one of the instances in the target group so that it can't access the DynamoDB recommendation table. We will get an instance id value. """); LaunchTemplateCreator templateCreator = new LaunchTemplateCreator(); AutoScaler autoScaler = new AutoScaler(); // Create a new instance profile based on badCredsProfileName. templateCreator.createInstanceProfile(policyFile, policyName, badCredsProfileName, roleName); String badInstanceId = autoScaler.getBadInstance(autoScalingGroupName); System.out.println("The bad instance id values used for this demo is " + badInstanceId); String profileAssociationId = autoScaler.getInstanceProfile(badInstanceId); System.out.println("The association Id value is " + profileAssociationId); System.out.println("Replacing the profile for instance " + badInstanceId + " with a profile that contains bad credentials"); autoScaler.replaceInstanceProfile(badInstanceId, badCredsProfileName, profileAssociationId); System.out.println( """ Now, sending a GET request to the load balancer endpoint returns either a recommendation or a static response, depending on which instance is selected by the load balancer. """); demoChoices(loadBalancer); System.out.println(""" Let's implement a deep health check. For this demo, a deep health check tests whether the web service can access the DynamoDB table that it depends on for recommendations. Note that the deep health check is only for ELB routing and not for Auto Scaling instance health. This kind of deep health check is not recommended for Auto Scaling instance health, because it risks accidental termination of all instances in the Auto Scaling group when a dependent service fails. """); System.out.println(""" By implementing deep health checks, the load balancer can detect when one of the instances is failing and take that instance out of rotation. """); paramHelper.put(paramHelper.healthCheck, "deep"); System.out.println(""" Now, checking target health indicates that the instance with bad credentials is unhealthy. Note that it might take a minute or two for the load balancer to detect the unhealthy instance. Sending a GET request to the load balancer endpoint always returns a recommendation, because the load balancer takes unhealthy instances out of its rotation. """); demoChoices(loadBalancer); System.out.println( """ Because the instances in this demo are controlled by an auto scaler, the simplest way to fix an unhealthy instance is to terminate it and let the auto scaler start a new instance to replace it. """); autoScaler.terminateInstance(badInstanceId); System.out.println(""" Even while the instance is terminating and the new instance is starting, sending a GET request to the web service continues to get a successful recommendation response because the load balancer routes requests to the healthy instances. After the replacement instance starts and reports as healthy, it is included in the load balancing rotation. Note that terminating and replacing an instance typically takes several minutes, during which time you can see the changing health check status until the new instance is running and healthy. """); demoChoices(loadBalancer); System.out.println( "If the recommendation service fails now, deep health checks mean all instances report as unhealthy."); paramHelper.put(paramHelper.tableName, "this-is-not-a-table"); demoChoices(loadBalancer); paramHelper.reset(); } public static void demoChoices(LoadBalancer loadBalancer) throws IOException, InterruptedException { String[] actions = { "Send a GET request to the load balancer endpoint.", "Check the health of load balancer targets.", "Go to the next part of the demo." }; Scanner scanner = new Scanner(System.in); while (true) { System.out.println("-".repeat(88)); System.out.println("See the current state of the service by selecting one of the following choices:"); for (int i = 0; i < actions.length; i++) { System.out.println(i + ": " + actions[i]); } try { System.out.print("\nWhich action would you like to take? "); int choice = scanner.nextInt(); System.out.println("-".repeat(88)); switch (choice) { case 0 -> { System.out.println("Request:\n"); System.out.println("GET http://" + loadBalancer.getEndpoint(lbName)); CloseableHttpClient httpClient = HttpClients.createDefault(); // Create an HTTP GET request to the ELB. HttpGet httpGet = new HttpGet("http://" + loadBalancer.getEndpoint(lbName)); // Execute the request and get the response. HttpResponse response = httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); System.out.println("HTTP Status Code: " + statusCode); // Display the JSON response BufferedReader reader = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); StringBuilder jsonResponse = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { jsonResponse.append(line); } reader.close(); // Print the formatted JSON response. System.out.println("Full Response:\n"); System.out.println(jsonResponse.toString()); // Close the HTTP client. httpClient.close(); } case 1 -> { System.out.println("\nChecking the health of load balancer targets:\n"); List<TargetHealthDescription> health = loadBalancer.checkTargetHealth(targetGroupName); for (TargetHealthDescription target : health) { System.out.printf("\tTarget %s on port %d is %s%n", target.target().id(), target.target().port(), target.targetHealth().stateAsString()); } System.out.println(""" Note that it can take a minute or two for the health check to update after changes are made. """); } case 2 -> { System.out.println("\nOkay, let's move on."); System.out.println("-".repeat(88)); return; // Exit the method when choice is 2 } default -> System.out.println("You must choose a value between 0-2. Please select again."); } } catch (java.util.InputMismatchException e) { System.out.println("Invalid input. Please select again."); scanner.nextLine(); // Clear the input buffer. } } } public static String readFileAsString(String filePath) throws IOException { byte[] bytes = Files.readAllBytes(Paths.get(filePath)); return new String(bytes); } }

创建一个包含自动扩缩和 Amazon EC2 操作的类。

public class AutoScaler { private static Ec2Client ec2Client; private static AutoScalingClient autoScalingClient; private static IamClient iamClient; private static SsmClient ssmClient; private IamClient getIAMClient() { if (iamClient == null) { iamClient = IamClient.builder() .region(Region.US_EAST_1) .build(); } return iamClient; } private SsmClient getSSMClient() { if (ssmClient == null) { ssmClient = SsmClient.builder() .region(Region.US_EAST_1) .build(); } return ssmClient; } private Ec2Client getEc2Client() { if (ec2Client == null) { ec2Client = Ec2Client.builder() .region(Region.US_EAST_1) .build(); } return ec2Client; } private AutoScalingClient getAutoScalingClient() { if (autoScalingClient == null) { autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); } return autoScalingClient; } /** * Terminates and instances in an EC2 Auto Scaling group. After an instance is * terminated, it can no longer be accessed. */ public void terminateInstance(String instanceId) { TerminateInstanceInAutoScalingGroupRequest terminateInstanceIRequest = TerminateInstanceInAutoScalingGroupRequest .builder() .instanceId(instanceId) .shouldDecrementDesiredCapacity(false) .build(); getAutoScalingClient().terminateInstanceInAutoScalingGroup(terminateInstanceIRequest); System.out.format("Terminated instance %s.", instanceId); } /** * Replaces the profile associated with a running instance. After the profile is * replaced, the instance is rebooted to ensure that it uses the new profile. * When * the instance is ready, Systems Manager is used to restart the Python web * server. */ public void replaceInstanceProfile(String instanceId, String newInstanceProfileName, String profileAssociationId) throws InterruptedException { // Create an IAM instance profile specification. software.amazon.awssdk.services.ec2.model.IamInstanceProfileSpecification iamInstanceProfile = software.amazon.awssdk.services.ec2.model.IamInstanceProfileSpecification .builder() .name(newInstanceProfileName) // Make sure 'newInstanceProfileName' is a valid IAM Instance Profile // name. .build(); // Replace the IAM instance profile association for the EC2 instance. ReplaceIamInstanceProfileAssociationRequest replaceRequest = ReplaceIamInstanceProfileAssociationRequest .builder() .iamInstanceProfile(iamInstanceProfile) .associationId(profileAssociationId) // Make sure 'profileAssociationId' is a valid association ID. .build(); try { getEc2Client().replaceIamInstanceProfileAssociation(replaceRequest); // Handle the response as needed. } catch (Ec2Exception e) { // Handle exceptions, log, or report the error. System.err.println("Error: " + e.getMessage()); } System.out.format("Replaced instance profile for association %s with profile %s.", profileAssociationId, newInstanceProfileName); TimeUnit.SECONDS.sleep(15); boolean instReady = false; int tries = 0; // Reboot after 60 seconds while (!instReady) { if (tries % 6 == 0) { getEc2Client().rebootInstances(RebootInstancesRequest.builder() .instanceIds(instanceId) .build()); System.out.println("Rebooting instance " + instanceId + " and waiting for it to be ready."); } tries++; try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } DescribeInstanceInformationResponse informationResponse = getSSMClient().describeInstanceInformation(); List<InstanceInformation> instanceInformationList = informationResponse.instanceInformationList(); for (InstanceInformation info : instanceInformationList) { if (info.instanceId().equals(instanceId)) { instReady = true; break; } } } SendCommandRequest sendCommandRequest = SendCommandRequest.builder() .instanceIds(instanceId) .documentName("AWS-RunShellScript") .parameters(Collections.singletonMap("commands", Collections.singletonList("cd / && sudo python3 server.py 80"))) .build(); getSSMClient().sendCommand(sendCommandRequest); System.out.println("Restarted the Python web server on instance " + instanceId + "."); } public void openInboundPort(String secGroupId, String port, String ipAddress) { AuthorizeSecurityGroupIngressRequest ingressRequest = AuthorizeSecurityGroupIngressRequest.builder() .groupName(secGroupId) .cidrIp(ipAddress) .fromPort(Integer.parseInt(port)) .build(); getEc2Client().authorizeSecurityGroupIngress(ingressRequest); System.out.format("Authorized ingress to %s on port %s from %s.", secGroupId, port, ipAddress); } /** * Detaches a role from an instance profile, detaches policies from the role, * and deletes all the resources. */ public void deleteInstanceProfile(String roleName, String profileName) { try { software.amazon.awssdk.services.iam.model.GetInstanceProfileRequest getInstanceProfileRequest = software.amazon.awssdk.services.iam.model.GetInstanceProfileRequest .builder() .instanceProfileName(profileName) .build(); GetInstanceProfileResponse response = getIAMClient().getInstanceProfile(getInstanceProfileRequest); String name = response.instanceProfile().instanceProfileName(); System.out.println(name); RemoveRoleFromInstanceProfileRequest profileRequest = RemoveRoleFromInstanceProfileRequest.builder() .instanceProfileName(profileName) .roleName(roleName) .build(); getIAMClient().removeRoleFromInstanceProfile(profileRequest); DeleteInstanceProfileRequest deleteInstanceProfileRequest = DeleteInstanceProfileRequest.builder() .instanceProfileName(profileName) .build(); getIAMClient().deleteInstanceProfile(deleteInstanceProfileRequest); System.out.println("Deleted instance profile " + profileName); DeleteRoleRequest deleteRoleRequest = DeleteRoleRequest.builder() .roleName(roleName) .build(); // List attached role policies. ListAttachedRolePoliciesResponse rolesResponse = getIAMClient() .listAttachedRolePolicies(role -> role.roleName(roleName)); List<AttachedPolicy> attachedPolicies = rolesResponse.attachedPolicies(); for (AttachedPolicy attachedPolicy : attachedPolicies) { DetachRolePolicyRequest request = DetachRolePolicyRequest.builder() .roleName(roleName) .policyArn(attachedPolicy.policyArn()) .build(); getIAMClient().detachRolePolicy(request); System.out.println("Detached and deleted policy " + attachedPolicy.policyName()); } getIAMClient().deleteRole(deleteRoleRequest); System.out.println("Instance profile and role deleted."); } catch (IamException e) { System.err.println(e.getMessage()); System.exit(1); } } public void deleteTemplate(String templateName) { getEc2Client().deleteLaunchTemplate(name -> name.launchTemplateName(templateName)); System.out.format(templateName + " was deleted."); } public void deleteAutoScaleGroup(String groupName) { DeleteAutoScalingGroupRequest deleteAutoScalingGroupRequest = DeleteAutoScalingGroupRequest.builder() .autoScalingGroupName(groupName) .forceDelete(true) .build(); getAutoScalingClient().deleteAutoScalingGroup(deleteAutoScalingGroupRequest); System.out.println(groupName + " was deleted."); } /* * Verify the default security group of the specified VPC allows ingress from * this * computer. This can be done by allowing ingress from this computer's IP * address. In some situations, such as connecting from a corporate network, you * must instead specify a prefix list ID. You can also temporarily open the port * to * any IP address while running this example. If you do, be sure to remove * public * access when you're done. * */ public GroupInfo verifyInboundPort(String VPC, int port, String ipAddress) { boolean portIsOpen = false; GroupInfo groupInfo = new GroupInfo(); try { Filter filter = Filter.builder() .name("group-name") .values("default") .build(); Filter filter1 = Filter.builder() .name("vpc-id") .values(VPC) .build(); DescribeSecurityGroupsRequest securityGroupsRequest = DescribeSecurityGroupsRequest.builder() .filters(filter, filter1) .build(); DescribeSecurityGroupsResponse securityGroupsResponse = getEc2Client() .describeSecurityGroups(securityGroupsRequest); String securityGroup = securityGroupsResponse.securityGroups().get(0).groupName(); groupInfo.setGroupName(securityGroup); for (SecurityGroup secGroup : securityGroupsResponse.securityGroups()) { System.out.println("Found security group: " + secGroup.groupId()); for (IpPermission ipPermission : secGroup.ipPermissions()) { if (ipPermission.fromPort() == port) { System.out.println("Found inbound rule: " + ipPermission); for (IpRange ipRange : ipPermission.ipRanges()) { String cidrIp = ipRange.cidrIp(); if (cidrIp.startsWith(ipAddress) || cidrIp.equals("0.0.0.0/0")) { System.out.println(cidrIp + " is applicable"); portIsOpen = true; } } if (!ipPermission.prefixListIds().isEmpty()) { System.out.println("Prefix lList is applicable"); portIsOpen = true; } if (!portIsOpen) { System.out .println("The inbound rule does not appear to be open to either this computer's IP," + " all IP addresses (0.0.0.0/0), or to a prefix list ID."); } else { break; } } } } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); } groupInfo.setPortOpen(portIsOpen); return groupInfo; } /* * Attaches an Elastic Load Balancing (ELB) target group to this EC2 Auto * Scaling group. * The target group specifies how the load balancer forward requests to the * instances * in the group. */ public void attachLoadBalancerTargetGroup(String asGroupName, String targetGroupARN) { try { AttachLoadBalancerTargetGroupsRequest targetGroupsRequest = AttachLoadBalancerTargetGroupsRequest.builder() .autoScalingGroupName(asGroupName) .targetGroupARNs(targetGroupARN) .build(); getAutoScalingClient().attachLoadBalancerTargetGroups(targetGroupsRequest); System.out.println("Attached load balancer to " + asGroupName); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } // Creates an EC2 Auto Scaling group with the specified size. public String[] createGroup(int groupSize, String templateName, String autoScalingGroupName) { // Get availability zones. software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesRequest zonesRequest = software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesRequest .builder() .build(); DescribeAvailabilityZonesResponse zonesResponse = getEc2Client().describeAvailabilityZones(zonesRequest); List<String> availabilityZoneNames = zonesResponse.availabilityZones().stream() .map(software.amazon.awssdk.services.ec2.model.AvailabilityZone::zoneName) .collect(Collectors.toList()); String availabilityZones = String.join(",", availabilityZoneNames); LaunchTemplateSpecification specification = LaunchTemplateSpecification.builder() .launchTemplateName(templateName) .version("$Default") .build(); String[] zones = availabilityZones.split(","); CreateAutoScalingGroupRequest groupRequest = CreateAutoScalingGroupRequest.builder() .launchTemplate(specification) .availabilityZones(zones) .maxSize(groupSize) .minSize(groupSize) .autoScalingGroupName(autoScalingGroupName) .build(); try { getAutoScalingClient().createAutoScalingGroup(groupRequest); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } System.out.println("Created an EC2 Auto Scaling group named " + autoScalingGroupName); return zones; } public String getDefaultVPC() { // Define the filter. Filter defaultFilter = Filter.builder() .name("is-default") .values("true") .build(); software.amazon.awssdk.services.ec2.model.DescribeVpcsRequest request = software.amazon.awssdk.services.ec2.model.DescribeVpcsRequest .builder() .filters(defaultFilter) .build(); DescribeVpcsResponse response = getEc2Client().describeVpcs(request); return response.vpcs().get(0).vpcId(); } // Gets the default subnets in a VPC for a specified list of Availability Zones. public List<Subnet> getSubnets(String vpcId, String[] availabilityZones) { List<Subnet> subnets = null; Filter vpcFilter = Filter.builder() .name("vpc-id") .values(vpcId) .build(); Filter azFilter = Filter.builder() .name("availability-zone") .values(availabilityZones) .build(); Filter defaultForAZ = Filter.builder() .name("default-for-az") .values("true") .build(); DescribeSubnetsRequest request = DescribeSubnetsRequest.builder() .filters(vpcFilter, azFilter, defaultForAZ) .build(); DescribeSubnetsResponse response = getEc2Client().describeSubnets(request); subnets = response.subnets(); return subnets; } // Gets data about the instances in the EC2 Auto Scaling group. public String getBadInstance(String groupName) { DescribeAutoScalingGroupsRequest request = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); DescribeAutoScalingGroupsResponse response = getAutoScalingClient().describeAutoScalingGroups(request); AutoScalingGroup autoScalingGroup = response.autoScalingGroups().get(0); List<String> instanceIds = autoScalingGroup.instances().stream() .map(instance -> instance.instanceId()) .collect(Collectors.toList()); String[] instanceIdArray = instanceIds.toArray(new String[0]); for (String instanceId : instanceIdArray) { System.out.println("Instance ID: " + instanceId); return instanceId; } return ""; } // Gets data about the profile associated with an instance. public String getInstanceProfile(String instanceId) { Filter filter = Filter.builder() .name("instance-id") .values(instanceId) .build(); DescribeIamInstanceProfileAssociationsRequest associationsRequest = DescribeIamInstanceProfileAssociationsRequest .builder() .filters(filter) .build(); DescribeIamInstanceProfileAssociationsResponse response = getEc2Client() .describeIamInstanceProfileAssociations(associationsRequest); return response.iamInstanceProfileAssociations().get(0).associationId(); } public void deleteRolesPolicies(String policyName, String roleName, String InstanceProfile) { ListPoliciesRequest listPoliciesRequest = ListPoliciesRequest.builder().build(); ListPoliciesResponse listPoliciesResponse = getIAMClient().listPolicies(listPoliciesRequest); for (Policy policy : listPoliciesResponse.policies()) { if (policy.policyName().equals(policyName)) { // List the entities (users, groups, roles) that are attached to the policy. software.amazon.awssdk.services.iam.model.ListEntitiesForPolicyRequest listEntitiesRequest = software.amazon.awssdk.services.iam.model.ListEntitiesForPolicyRequest .builder() .policyArn(policy.arn()) .build(); ListEntitiesForPolicyResponse listEntitiesResponse = iamClient .listEntitiesForPolicy(listEntitiesRequest); if (!listEntitiesResponse.policyGroups().isEmpty() || !listEntitiesResponse.policyUsers().isEmpty() || !listEntitiesResponse.policyRoles().isEmpty()) { // Detach the policy from any entities it is attached to. DetachRolePolicyRequest detachPolicyRequest = DetachRolePolicyRequest.builder() .policyArn(policy.arn()) .roleName(roleName) // Specify the name of the IAM role .build(); getIAMClient().detachRolePolicy(detachPolicyRequest); System.out.println("Policy detached from entities."); } // Now, you can delete the policy. DeletePolicyRequest deletePolicyRequest = DeletePolicyRequest.builder() .policyArn(policy.arn()) .build(); getIAMClient().deletePolicy(deletePolicyRequest); System.out.println("Policy deleted successfully."); break; } } // List the roles associated with the instance profile ListInstanceProfilesForRoleRequest listRolesRequest = ListInstanceProfilesForRoleRequest.builder() .roleName(roleName) .build(); // Detach the roles from the instance profile ListInstanceProfilesForRoleResponse listRolesResponse = iamClient.listInstanceProfilesForRole(listRolesRequest); for (software.amazon.awssdk.services.iam.model.InstanceProfile profile : listRolesResponse.instanceProfiles()) { RemoveRoleFromInstanceProfileRequest removeRoleRequest = RemoveRoleFromInstanceProfileRequest.builder() .instanceProfileName(InstanceProfile) .roleName(roleName) // Remove the extra dot here .build(); getIAMClient().removeRoleFromInstanceProfile(removeRoleRequest); System.out.println("Role " + roleName + " removed from instance profile " + InstanceProfile); } // Delete the instance profile after removing all roles DeleteInstanceProfileRequest deleteInstanceProfileRequest = DeleteInstanceProfileRequest.builder() .instanceProfileName(InstanceProfile) .build(); getIAMClient().deleteInstanceProfile(r -> r.instanceProfileName(InstanceProfile)); System.out.println(InstanceProfile + " Deleted"); System.out.println("All roles and policies are deleted."); } }

创建一个包含弹性负载均衡操作的类。

public class LoadBalancer { public ElasticLoadBalancingV2Client elasticLoadBalancingV2Client; public ElasticLoadBalancingV2Client getLoadBalancerClient() { if (elasticLoadBalancingV2Client == null) { elasticLoadBalancingV2Client = ElasticLoadBalancingV2Client.builder() .region(Region.US_EAST_1) .build(); } return elasticLoadBalancingV2Client; } // Checks the health of the instances in the target group. public List<TargetHealthDescription> checkTargetHealth(String targetGroupName) { DescribeTargetGroupsRequest targetGroupsRequest = DescribeTargetGroupsRequest.builder() .names(targetGroupName) .build(); DescribeTargetGroupsResponse tgResponse = getLoadBalancerClient().describeTargetGroups(targetGroupsRequest); DescribeTargetHealthRequest healthRequest = DescribeTargetHealthRequest.builder() .targetGroupArn(tgResponse.targetGroups().get(0).targetGroupArn()) .build(); DescribeTargetHealthResponse healthResponse = getLoadBalancerClient().describeTargetHealth(healthRequest); return healthResponse.targetHealthDescriptions(); } // Gets the HTTP endpoint of the load balancer. public String getEndpoint(String lbName) { DescribeLoadBalancersResponse res = getLoadBalancerClient() .describeLoadBalancers(describe -> describe.names(lbName)); return res.loadBalancers().get(0).dnsName(); } // Deletes a load balancer. public void deleteLoadBalancer(String lbName) { try { // Use a waiter to delete the Load Balancer. DescribeLoadBalancersResponse res = getLoadBalancerClient() .describeLoadBalancers(describe -> describe.names(lbName)); ElasticLoadBalancingV2Waiter loadBalancerWaiter = getLoadBalancerClient().waiter(); DescribeLoadBalancersRequest request = DescribeLoadBalancersRequest.builder() .loadBalancerArns(res.loadBalancers().get(0).loadBalancerArn()) .build(); getLoadBalancerClient().deleteLoadBalancer( builder -> builder.loadBalancerArn(res.loadBalancers().get(0).loadBalancerArn())); WaiterResponse<DescribeLoadBalancersResponse> waiterResponse = loadBalancerWaiter .waitUntilLoadBalancersDeleted(request); waiterResponse.matched().response().ifPresent(System.out::println); } catch (ElasticLoadBalancingV2Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); } System.out.println(lbName + " was deleted."); } // Deletes the target group. public void deleteTargetGroup(String targetGroupName) { try { DescribeTargetGroupsResponse res = getLoadBalancerClient() .describeTargetGroups(describe -> describe.names(targetGroupName)); getLoadBalancerClient() .deleteTargetGroup(builder -> builder.targetGroupArn(res.targetGroups().get(0).targetGroupArn())); } catch (ElasticLoadBalancingV2Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); } System.out.println(targetGroupName + " was deleted."); } // Verify this computer can successfully send a GET request to the load balancer // endpoint. public boolean verifyLoadBalancerEndpoint(String elbDnsName) throws IOException, InterruptedException { boolean success = false; int retries = 3; CloseableHttpClient httpClient = HttpClients.createDefault(); // Create an HTTP GET request to the ELB. HttpGet httpGet = new HttpGet("http://" + elbDnsName); try { while ((!success) && (retries > 0)) { // Execute the request and get the response. HttpResponse response = httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); System.out.println("HTTP Status Code: " + statusCode); if (statusCode == 200) { success = true; } else { retries--; System.out.println("Got connection error from load balancer endpoint, retrying..."); TimeUnit.SECONDS.sleep(15); } } } catch (org.apache.http.conn.HttpHostConnectException e) { System.out.println(e.getMessage()); } System.out.println("Status.." + success); return success; } /* * Creates an Elastic Load Balancing target group. The target group specifies * how * the load balancer forward requests to instances in the group and how instance * health is checked. */ public String createTargetGroup(String protocol, int port, String vpcId, String targetGroupName) { CreateTargetGroupRequest targetGroupRequest = CreateTargetGroupRequest.builder() .healthCheckPath("/healthcheck") .healthCheckTimeoutSeconds(5) .port(port) .vpcId(vpcId) .name(targetGroupName) .protocol(protocol) .build(); CreateTargetGroupResponse targetGroupResponse = getLoadBalancerClient().createTargetGroup(targetGroupRequest); String targetGroupArn = targetGroupResponse.targetGroups().get(0).targetGroupArn(); String targetGroup = targetGroupResponse.targetGroups().get(0).targetGroupName(); System.out.println("The " + targetGroup + " was created with ARN" + targetGroupArn); return targetGroupArn; } /* * Creates an Elastic Load Balancing load balancer that uses the specified * subnets * and forwards requests to the specified target group. */ public String createLoadBalancer(List<Subnet> subnetIds, String targetGroupARN, String lbName, int port, String protocol) { try { List<String> subnetIdStrings = subnetIds.stream() .map(Subnet::subnetId) .collect(Collectors.toList()); CreateLoadBalancerRequest balancerRequest = CreateLoadBalancerRequest.builder() .subnets(subnetIdStrings) .name(lbName) .scheme("internet-facing") .build(); // Create and wait for the load balancer to become available. CreateLoadBalancerResponse lsResponse = getLoadBalancerClient().createLoadBalancer(balancerRequest); String lbARN = lsResponse.loadBalancers().get(0).loadBalancerArn(); ElasticLoadBalancingV2Waiter loadBalancerWaiter = getLoadBalancerClient().waiter(); DescribeLoadBalancersRequest request = DescribeLoadBalancersRequest.builder() .loadBalancerArns(lbARN) .build(); System.out.println("Waiting for Load Balancer " + lbName + " to become available."); WaiterResponse<DescribeLoadBalancersResponse> waiterResponse = loadBalancerWaiter .waitUntilLoadBalancerAvailable(request); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("Load Balancer " + lbName + " is available."); // Get the DNS name (endpoint) of the load balancer. String lbDNSName = lsResponse.loadBalancers().get(0).dnsName(); System.out.println("*** Load Balancer DNS Name: " + lbDNSName); // Create a listener for the load balance. Action action = Action.builder() .targetGroupArn(targetGroupARN) .type("forward") .build(); CreateListenerRequest listenerRequest = CreateListenerRequest.builder() .loadBalancerArn(lsResponse.loadBalancers().get(0).loadBalancerArn()) .defaultActions(action) .port(port) .protocol(protocol) .defaultActions(action) .build(); getLoadBalancerClient().createListener(listenerRequest); System.out.println("Created listener to forward traffic from load balancer " + lbName + " to target group " + targetGroupARN); // Return the load balancer DNS name. return lbDNSName; } catch (ElasticLoadBalancingV2Exception e) { e.printStackTrace(); } return ""; } }

创建一个使用 DynamoDB 模拟推荐服务的类。

public class Database { private static DynamoDbClient dynamoDbClient; public static DynamoDbClient getDynamoDbClient() { if (dynamoDbClient == null) { dynamoDbClient = DynamoDbClient.builder() .region(Region.US_EAST_1) .build(); } return dynamoDbClient; } // Checks to see if the Amazon DynamoDB table exists. private boolean doesTableExist(String tableName) { try { // Describe the table and catch any exceptions. DescribeTableRequest describeTableRequest = DescribeTableRequest.builder() .tableName(tableName) .build(); getDynamoDbClient().describeTable(describeTableRequest); System.out.println("Table '" + tableName + "' exists."); return true; } catch (ResourceNotFoundException e) { System.out.println("Table '" + tableName + "' does not exist."); } catch (DynamoDbException e) { System.err.println("Error checking table existence: " + e.getMessage()); } return false; } /* * Creates a DynamoDB table to use a recommendation service. The table has a * hash key named 'MediaType' that defines the type of media recommended, such * as * Book or Movie, and a range key named 'ItemId' that, combined with the * MediaType, * forms a unique identifier for the recommended item. */ public void createTable(String tableName, String fileName) throws IOException { // First check to see if the table exists. boolean doesExist = doesTableExist(tableName); if (!doesExist) { DynamoDbWaiter dbWaiter = getDynamoDbClient().waiter(); CreateTableRequest createTableRequest = CreateTableRequest.builder() .tableName(tableName) .attributeDefinitions( AttributeDefinition.builder() .attributeName("MediaType") .attributeType(ScalarAttributeType.S) .build(), AttributeDefinition.builder() .attributeName("ItemId") .attributeType(ScalarAttributeType.N) .build()) .keySchema( KeySchemaElement.builder() .attributeName("MediaType") .keyType(KeyType.HASH) .build(), KeySchemaElement.builder() .attributeName("ItemId") .keyType(KeyType.RANGE) .build()) .provisionedThroughput( ProvisionedThroughput.builder() .readCapacityUnits(5L) .writeCapacityUnits(5L) .build()) .build(); getDynamoDbClient().createTable(createTableRequest); System.out.println("Creating table " + tableName + "..."); // Wait until the Amazon DynamoDB table is created. DescribeTableRequest tableRequest = DescribeTableRequest.builder() .tableName(tableName) .build(); WaiterResponse<DescribeTableResponse> waiterResponse = dbWaiter.waitUntilTableExists(tableRequest); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("Table " + tableName + " created."); // Add records to the table. populateTable(fileName, tableName); } } public void deleteTable(String tableName) { getDynamoDbClient().deleteTable(table -> table.tableName(tableName)); System.out.println("Table " + tableName + " deleted."); } // Populates the table with data located in a JSON file using the DynamoDB // enhanced client. public void populateTable(String fileName, String tableName) throws IOException { DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(getDynamoDbClient()) .build(); ObjectMapper objectMapper = new ObjectMapper(); File jsonFile = new File(fileName); JsonNode rootNode = objectMapper.readTree(jsonFile); DynamoDbTable<Recommendation> mappedTable = enhancedClient.table(tableName, TableSchema.fromBean(Recommendation.class)); for (JsonNode currentNode : rootNode) { String mediaType = currentNode.path("MediaType").path("S").asText(); int itemId = currentNode.path("ItemId").path("N").asInt(); String title = currentNode.path("Title").path("S").asText(); String creator = currentNode.path("Creator").path("S").asText(); // Create a Recommendation object and set its properties. Recommendation rec = new Recommendation(); rec.setMediaType(mediaType); rec.setItemId(itemId); rec.setTitle(title); rec.setCreator(creator); // Put the item into the DynamoDB table. mappedTable.putItem(rec); // Add the Recommendation to the list. } System.out.println("Added all records to the " + tableName); } }

创建一个包含 Systems Manager 操作的类。

public class ParameterHelper { String tableName = "doc-example-resilient-architecture-table"; String dyntable = "doc-example-recommendation-service"; String failureResponse = "doc-example-resilient-architecture-failure-response"; String healthCheck = "doc-example-resilient-architecture-health-check"; public void reset() { put(dyntable, tableName); put(failureResponse, "none"); put(healthCheck, "shallow"); } public void put(String name, String value) { SsmClient ssmClient = SsmClient.builder() .region(Region.US_EAST_1) .build(); PutParameterRequest parameterRequest = PutParameterRequest.builder() .name(name) .value(value) .overwrite(true) .type("String") .build(); ssmClient.putParameter(parameterRequest); System.out.printf("Setting demo parameter %s to '%s'.", name, value); } }

以下代码示例展示了如何:

  • 创建包含启动模板和可用区的 Amazon EC2 Auto Scaling 组,并获取有关正在运行的实例的信息。

  • 启用 Amazon CloudWatch 指标收集。

  • 更新组的所需容量,并等待实例启动。

  • 终止组中的实例。

  • 列出为响应用户请求和容量变化而发生的扩缩活动。

  • 获取 CloudWatch 指标的统计数据,然后清理资源。

适用于 Java 2.x 的 SDK
注意

还有更多相关信息 GitHub。在 AWS 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/** * Before running this SDK for Java (v2) code example, set up your development * environment, including your credentials. * * For more information, see the following documentation: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html * * In addition, create a launch template. For more information, see the * following topic: * * https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html#create-launch-template * * This code example performs the following operations: * 1. Creates an Auto Scaling group using an AutoScalingWaiter. * 2. Gets a specific Auto Scaling group and returns an instance Id value. * 3. Describes Auto Scaling with the Id value. * 4. Enables metrics collection. * 5. Update an Auto Scaling group. * 6. Describes Account details. * 7. Describe account details" * 8. Updates an Auto Scaling group to use an additional instance. * 9. Gets the specific Auto Scaling group and gets the number of instances. * 10. List the scaling activities that have occurred for the group. * 11. Terminates an instance in the Auto Scaling group. * 12. Stops the metrics collection. * 13. Deletes the Auto Scaling group. */ public class AutoScalingScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); public static void main(String[] args) throws InterruptedException { final String usage = """ Usage: <groupName> <launchTemplateName> <vpcZoneId> Where: groupName - The name of the Auto Scaling group. launchTemplateName - The name of the launch template.\s vpcZoneId - A subnet Id for a virtual private cloud (VPC) where instances in the Auto Scaling group can be created. """; if (args.length != 3) { System.out.println(usage); System.exit(1); } String groupName = args[0]; String launchTemplateName = args[1]; String vpcZoneId = args[2]; AutoScalingClient autoScalingClient = AutoScalingClient.builder() .region(Region.US_EAST_1) .build(); System.out.println(DASHES); System.out.println("Welcome to the Amazon EC2 Auto Scaling example scenario."); System.out.println(DASHES); System.out.println(DASHES); System.out.println("1. Create an Auto Scaling group named " + groupName); createAutoScalingGroup(autoScalingClient, groupName, launchTemplateName, vpcZoneId); System.out.println( "Wait 1 min for the resources, including the instance. Otherwise, an empty instance Id is returned"); Thread.sleep(60000); System.out.println(DASHES); System.out.println(DASHES); System.out.println("2. Get Auto Scale group Id value"); String instanceId = getSpecificAutoScalingGroups(autoScalingClient, groupName); if (instanceId.compareTo("") == 0) { System.out.println("Error - no instance Id value"); System.exit(1); } else { System.out.println("The instance Id value is " + instanceId); } System.out.println(DASHES); System.out.println(DASHES); System.out.println("3. Describe Auto Scaling with the Id value " + instanceId); describeAutoScalingInstance(autoScalingClient, instanceId); System.out.println(DASHES); System.out.println(DASHES); System.out.println("4. Enable metrics collection " + instanceId); enableMetricsCollection(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("5. Update an Auto Scaling group to update max size to 3"); updateAutoScalingGroup(autoScalingClient, groupName, launchTemplateName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("6. Describe Auto Scaling groups"); describeAutoScalingGroups(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("7. Describe account details"); describeAccountLimits(autoScalingClient); System.out.println( "Wait 1 min for the resources, including the instance. Otherwise, an empty instance Id is returned"); Thread.sleep(60000); System.out.println(DASHES); System.out.println(DASHES); System.out.println("8. Set desired capacity to 2"); setDesiredCapacity(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("9. Get the two instance Id values and state"); getSpecificAutoScalingGroups(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("10. List the scaling activities that have occurred for the group"); describeScalingActivities(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("11. Terminate an instance in the Auto Scaling group"); terminateInstanceInAutoScalingGroup(autoScalingClient, instanceId); System.out.println(DASHES); System.out.println(DASHES); System.out.println("12. Stop the metrics collection"); disableMetricsCollection(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("13. Delete the Auto Scaling group"); deleteAutoScalingGroup(autoScalingClient, groupName); System.out.println(DASHES); System.out.println(DASHES); System.out.println("The Scenario has successfully completed."); System.out.println(DASHES); autoScalingClient.close(); } public static void describeScalingActivities(AutoScalingClient autoScalingClient, String groupName) { try { DescribeScalingActivitiesRequest scalingActivitiesRequest = DescribeScalingActivitiesRequest.builder() .autoScalingGroupName(groupName) .maxRecords(10) .build(); DescribeScalingActivitiesResponse response = autoScalingClient .describeScalingActivities(scalingActivitiesRequest); List<Activity> activities = response.activities(); for (Activity activity : activities) { System.out.println("The activity Id is " + activity.activityId()); System.out.println("The activity details are " + activity.details()); } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void setDesiredCapacity(AutoScalingClient autoScalingClient, String groupName) { try { SetDesiredCapacityRequest capacityRequest = SetDesiredCapacityRequest.builder() .autoScalingGroupName(groupName) .desiredCapacity(2) .build(); autoScalingClient.setDesiredCapacity(capacityRequest); System.out.println("You have set the DesiredCapacity to 2"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void createAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName, String launchTemplateName, String vpcZoneId) { try { AutoScalingWaiter waiter = autoScalingClient.waiter(); LaunchTemplateSpecification templateSpecification = LaunchTemplateSpecification.builder() .launchTemplateName(launchTemplateName) .build(); CreateAutoScalingGroupRequest request = CreateAutoScalingGroupRequest.builder() .autoScalingGroupName(groupName) .availabilityZones("us-east-1a") .launchTemplate(templateSpecification) .maxSize(1) .minSize(1) .vpcZoneIdentifier(vpcZoneId) .build(); autoScalingClient.createAutoScalingGroup(request); DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); WaiterResponse<DescribeAutoScalingGroupsResponse> waiterResponse = waiter .waitUntilGroupExists(groupsRequest); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("Auto Scaling Group created"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void describeAutoScalingInstance(AutoScalingClient autoScalingClient, String id) { try { DescribeAutoScalingInstancesRequest describeAutoScalingInstancesRequest = DescribeAutoScalingInstancesRequest .builder() .instanceIds(id) .build(); DescribeAutoScalingInstancesResponse response = autoScalingClient .describeAutoScalingInstances(describeAutoScalingInstancesRequest); List<AutoScalingInstanceDetails> instances = response.autoScalingInstances(); for (AutoScalingInstanceDetails instance : instances) { System.out.println("The instance lifecycle state is: " + instance.lifecycleState()); } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void describeAutoScalingGroups(AutoScalingClient autoScalingClient, String groupName) { try { DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .maxRecords(10) .build(); DescribeAutoScalingGroupsResponse response = autoScalingClient.describeAutoScalingGroups(groupsRequest); List<AutoScalingGroup> groups = response.autoScalingGroups(); for (AutoScalingGroup group : groups) { System.out.println("*** The service to use for the health checks: " + group.healthCheckType()); } } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static String getSpecificAutoScalingGroups(AutoScalingClient autoScalingClient, String groupName) { try { String instanceId = ""; DescribeAutoScalingGroupsRequest scalingGroupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); DescribeAutoScalingGroupsResponse response = autoScalingClient .describeAutoScalingGroups(scalingGroupsRequest); List<AutoScalingGroup> groups = response.autoScalingGroups(); for (AutoScalingGroup group : groups) { System.out.println("The group name is " + group.autoScalingGroupName()); System.out.println("The group ARN is " + group.autoScalingGroupARN()); List<Instance> instances = group.instances(); for (Instance instance : instances) { instanceId = instance.instanceId(); System.out.println("The instance id is " + instanceId); System.out.println("The lifecycle state is " + instance.lifecycleState()); } } return instanceId; } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } return ""; } public static void enableMetricsCollection(AutoScalingClient autoScalingClient, String groupName) { try { EnableMetricsCollectionRequest collectionRequest = EnableMetricsCollectionRequest.builder() .autoScalingGroupName(groupName) .metrics("GroupMaxSize") .granularity("1Minute") .build(); autoScalingClient.enableMetricsCollection(collectionRequest); System.out.println("The enable metrics collection operation was successful"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void disableMetricsCollection(AutoScalingClient autoScalingClient, String groupName) { try { DisableMetricsCollectionRequest disableMetricsCollectionRequest = DisableMetricsCollectionRequest.builder() .autoScalingGroupName(groupName) .metrics("GroupMaxSize") .build(); autoScalingClient.disableMetricsCollection(disableMetricsCollectionRequest); System.out.println("The disable metrics collection operation was successful"); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void describeAccountLimits(AutoScalingClient autoScalingClient) { try { DescribeAccountLimitsResponse response = autoScalingClient.describeAccountLimits(); System.out.println("The max number of auto scaling groups is " + response.maxNumberOfAutoScalingGroups()); System.out.println("The current number of auto scaling groups is " + response.numberOfAutoScalingGroups()); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void updateAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName, String launchTemplateName) { try { AutoScalingWaiter waiter = autoScalingClient.waiter(); LaunchTemplateSpecification templateSpecification = LaunchTemplateSpecification.builder() .launchTemplateName(launchTemplateName) .build(); UpdateAutoScalingGroupRequest groupRequest = UpdateAutoScalingGroupRequest.builder() .maxSize(3) .autoScalingGroupName(groupName) .launchTemplate(templateSpecification) .build(); autoScalingClient.updateAutoScalingGroup(groupRequest); DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder() .autoScalingGroupNames(groupName) .build(); WaiterResponse<DescribeAutoScalingGroupsResponse> waiterResponse = waiter .waitUntilGroupInService(groupsRequest); waiterResponse.matched().response().ifPresent(System.out::println); System.out.println("You successfully updated the auto scaling group " + groupName); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void terminateInstanceInAutoScalingGroup(AutoScalingClient autoScalingClient, String instanceId) { try { TerminateInstanceInAutoScalingGroupRequest request = TerminateInstanceInAutoScalingGroupRequest.builder() .instanceId(instanceId) .shouldDecrementDesiredCapacity(false) .build(); autoScalingClient.terminateInstanceInAutoScalingGroup(request); System.out.println("You have terminated instance " + instanceId); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } public static void deleteAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName) { try { DeleteAutoScalingGroupRequest deleteAutoScalingGroupRequest = DeleteAutoScalingGroupRequest.builder() .autoScalingGroupName(groupName) .forceDelete(true) .build(); autoScalingClient.deleteAutoScalingGroup(deleteAutoScalingGroupRequest); System.out.println("You successfully deleted " + groupName); } catch (AutoScalingException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } }