基于HTTP请求自动启停AWS EC2开发服务器方案咨询
Great question—this is such a common pain point with dev servers on EC2, and AWS has all the tools to build a clean, cost-effective solution. Let me walk you through a step-by-step setup that I’ve used for my own projects:
We’ll use API Gateway + Lambda to handle the HTTP trigger and kick off the EC2 instance. This is serverless, so you only pay for actual requests, no idle costs.
Setup Steps:
- Create a Lambda Function:
- Use Python (or your preferred runtime) with permissions to call
ec2:StartInstancesandec2:DescribeInstances(to avoid trying to start an already running instance). Attach an IAM role with these permissions plus CloudWatch Logs access for debugging. - Here’s a sample function:
import boto3 from datetime import datetime ec2 = boto3.client('ec2') INSTANCE_ID = 'your-ec2-instance-id' # Replace with your actual instance ID def lambda_handler(event, context): # Check current instance state first response = ec2.describe_instances(InstanceIds=[INSTANCE_ID]) state = response['Reservations'][0]['Instances'][0]['State']['Name'] if state == 'stopped': ec2.start_instances(InstanceIds=[INSTANCE_ID]) return { 'statusCode': 200, 'body': f"Starting instance {INSTANCE_ID}. It'll be ready in ~2-5 minutes." } elif state == 'running': return { 'statusCode': 200, 'body': f"Instance {INSTANCE_ID} is already up and running." } else: return { 'statusCode': 400, 'body': f"Instance {INSTANCE_ID} is in {state} state—can't start right now." }
- Use Python (or your preferred runtime) with permissions to call
- Configure API Gateway:
- Create an HTTP API (cheaper and simpler than REST API for this use case) and add a route (e.g.,
/start-dev-server) that integrates with your Lambda function. Enable CORS if you plan to call this endpoint from a browser. - Test it out: Send a GET/POST request to your API endpoint, and you’ll get a clear response confirming the instance’s status.
- Create an HTTP API (cheaper and simpler than REST API for this use case) and add a route (e.g.,
To handle idle shutdown, we’ll track the last request time and use EventBridge + Lambda + DynamoDB to check for inactivity and stop the instance automatically.
Setup Steps:
- Create a DynamoDB Table:
- Make a simple table with
InstanceIDas the string primary key, and add an attributeLastRequestTimestamp(number, Unix timestamp). The free tier is more than enough for this single record.
- Make a simple table with
- Update the Start Lambda:
- Add code to update the DynamoDB table every time a request comes in, so we always have the latest activity time:
# Add these imports/initializations at the top dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('DevServerActivity') # Replace with your table name # ... after handling the instance start/running check ... table.put_item( Item={ 'InstanceID': INSTANCE_ID, 'LastRequestTimestamp': int(datetime.now().timestamp()) } )
- Add code to update the DynamoDB table every time a request comes in, so we always have the latest activity time:
- Create a Stop Check Lambda:
- This function runs on a schedule, checks the last activity time, and stops the instance if it’s been idle for 1 hour:
import boto3 from datetime import datetime ec2 = boto3.client('ec2') dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('DevServerActivity') INSTANCE_ID = 'your-ec2-instance-id' IDLE_THRESHOLD = 3600 # 1 hour in seconds def lambda_handler(event, context): # Fetch the last activity timestamp response = table.get_item(Key={'InstanceID': INSTANCE_ID}) if 'Item' not in response: return {'statusCode': 200, 'body': "No activity recorded for this instance yet."} last_request = response['Item']['LastRequestTimestamp'] current_time = int(datetime.now().timestamp()) time_since_last = current_time - last_request # Check instance state and idle duration ec2_response = ec2.describe_instances(InstanceIds=[INSTANCE_ID]) state = ec2_response['Reservations'][0]['Instances'][0]['State']['Name'] if state == 'running' and time_since_last >= IDLE_THRESHOLD: ec2.stop_instances(InstanceIds=[INSTANCE_ID]) return { 'statusCode': 200, 'body': f"Instance {INSTANCE_ID} stopped due to 1 hour of inactivity." } else: return { 'statusCode': 200, 'body': f"Instance is {state} | Last activity {time_since_last} seconds ago." }
- This function runs on a schedule, checks the last activity time, and stops the instance if it’s been idle for 1 hour:
- Set Up EventBridge Schedule:
- Create a rule that runs the Stop Check Lambda every 5 minutes (or 10 minutes, depending on how quickly you want to shut down). This ensures we catch the 1-hour mark without unnecessary frequent runs.
If your instance takes a few minutes to boot and start serving requests, you can modify the Start Lambda to poll the instance’s status (and even your dev server’s HTTP endpoint) before returning a "ready" response. For more complex workflows, use Step Functions to orchestrate the start → wait for running → wait for service ready → notify user flow.
Make sure your Lambda roles have these permissions:
- For the Start Lambda:
ec2:DescribeInstances,ec2:StartInstances,dynamodb:PutItem,logs:CreateLogGroup,logs:CreateLogStream,logs:PutLogEvents - For the Stop Check Lambda:
ec2:DescribeInstances,ec2:StopInstances,dynamodb:GetItem,logs:*
This setup is lightweight, cost-efficient, and requires almost no maintenance once configured. I’ve been using this for my own EC2 dev server for months, and it’s saved me a ton of unnecessary charges.
内容的提问来源于stack exchange,提问作者ozkolonur

