先上代码
假设我们有一个线上lambda做ETL的Extract和Load,线上的lambda接受以下event:
{
"projectId": 50234,
"teamId": 69583,
"forDate": "2018-03-21"
}
处理成功lambda就返回以下message:
{
"workers": 35,
"hours": 237.4
}
如何实现
首先,当然是定义对应的Java接口, 假设lambda的名字是insightsRollup:
public interface InsightService {
@LambdaFunction(functionName="insightsRollup")
RollupResponse insightsRollup(InsightsRollupEvent input);
}
输入和输出:
public class InsightsRollupEvent {
private Integer projectId;
private Integer teamId;
private LocalDate forDate;
...
}
public class RollupResponse {
private Integer workers;
private Double hours;
...
}
然后呢?然后就基本完成了!
接下来的工作可以都交给LambdaInvokerFactory来构造InsightService的实例:
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
insightService = LambdaInvokerFactory.builder()
.lambdaClient(
AWSLambdaClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build()
)
.build(InsightService.class);
然后你就可以像本地方法一样使用insightService.insightService()调用远端的insightRollup.
做了什么
lambda是部署在aws的服务器上的,我们是如何把请求发送到远端的服务器并接受返回的呢。打开log4j测试一下:
log4j.rootLogger = DEBUG
@Test
public void insightsRollup() {
RollupResponse resp = insightService().insightsRollup(new InsightsRollupEvent(
50234,
69583,
LocalDate.now()
));
System.out.println(resp)
}
运行,注意到下面:
Serialized request object to '{"projectId": 50234,"teamId": 69583,"forDate": "2018-03-21"}'
说明数据是通过json传输的
还有下面:
[com.amazonaws.request]: Sending Request: POST https://lambda.ap-southeast-2.amazonaws.com/2015-03-31/functions/insightsRollup/invocations Headers: (X-Amz-Invocation-Type: RequestResponse, User-Agent: aws-sdk-java/1.11.163 Mac_OS_X/10.12.3 Java_HotSpot(TM)_64-Bit_Server_VM/25.131-b11/1.8.0_131, amz-sdk-invocation-id: 6cc1a52f-dd73-4de4-e249-8c1555db8eea, X-Amz-Log-Type: None, Content-Type: , )
这其实就是lambda的rest api.
LambdaInvokerFactory做得就是让你用Interface和Annotation的方式,帮你构造一个rest client,达到本地调用lambda的目的.
注意这种调用方式是同步的
为什么要使用Java同步调用lambda?
最近开始大规模使用lambda, 或者说serverless以后,这是我经常思考的问题。以前我们讨论SOA,再到后来micro-service,然后现在又出现nano-service. 这些大方向的东西以后再说,单说这种同步调用lambda的方式,我觉得好处就有:
-
具有
micro/nano service的好处,你可以使用不同的语言开发lambda,分布式的架构迫使你定义清晰的Interface和事务边界,独立部署,独立伸缩,独立发布。 -
避免了
micro/nano service架构在基础建设上的overhead. 相比较api gateway,sns等触发lambda的方式, 这种方式明显简单得多, 不需要很多的基础架构设置. 而lambda本身具有不需要管理服务器和便宜的好处。 -
rest同步的方式避免了分布式异步事务的问题
当然现在看来缺点是性能,But who cares~