实战:将 Spring Boot 应用改造为 Serverless 函数
步骤 1:定义一个“函数”而非“Controller”
// 不再使用 @RestController
// 而是实现 Function 接口
@Component
public class GreetingFunction implements Function<String, String> {
@Override
public String apply(String name) {
return "Hello, " + (name.isEmpty() ? "World" : name) + "!";
}
}
✅ 业务逻辑 = 函数输入 → 输出。
步骤 2:添加 Spring Cloud Function 依赖
<dependencies>
<!-- Spring Boot Web (可选,用于本地测试) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Function Web Adapter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
</dependency>
<!-- AWS Lambda Adapter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
<!-- AWS Lambda Core -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
步骤 3:配置 application.yml
# 指定默认处理的函数
spring:
cloud:
function:
definition: greetingFunction
步骤 4:创建 AWS Lambda Handler
// AWSLambdaHandler.java
public class AWSLambdaHandler implements RequestStreamHandler {
private final FunctionInvoker invoker = new FunctionInvoker();
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
throws IOException {
invoker.handleRequest(inputStream, outputStream, context);
}
}
步骤 5:构建并部署到 AWS Lambda
1. 构建 Uber JAR
mvn clean package
2. 创建 Lambda 函数
- Runtime: Java 17
- Handler:
com.example.AWSLambdaHandler::handleRequest
- Upload
target/your-app.jar
3. 配置 API Gateway
- 创建 HTTP API
- 集成到 Lambda 函数
- 获取公网 URL
curl https://your-api.execute-api.region.amazonaws.com/greetingFunction -d '"Spring"'
# Output: "Hello, Spring!"
步骤 6:解决冷启动问题(关键!)
方案 1:使用 Provisioned Concurrency
- 预热 1~2 个实例常驻内存
- 代价:需付费
方案 2:使用 GraalVM Native Image(推荐)
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
# 构建 Native Image
mvn native:compile
# 生成的可执行文件 < 50MB,启动时间 < 100ms
✅ Native Image 是 Serverless 的“终极武器”。
步骤 7:事件驱动(S3 文件上传触发)
@Component
public class S3ProcessFunction implements Consumer<S3Event> {
@Override
public void accept(S3Event event) {
event.getRecords().forEach(record -> {
String bucket = record.getS3().getBucket().getName();
String key = record.getS3().getObject().getKey();
System.out.println("Processing file: s3://" + bucket + "/" + key);
// 处理文件...
});
}
}
- 配置 S3 存储桶事件 → 触发 Lambda
- 无需轮询,实时响应