寫在前面
使用aws lambda已經一年多了,下面使用java構建一個簡單的lambda服務,大家可以自己擴展想要的功能,廢話不多說,開始吧。
AWS 上 Java Lambda 應用記要
public class LambdaFunctionHandler implements RequestHandler<Object,Object > {
int warmNum = 0;
public GatewayResponse handleRequest(Object input, Context context) {
Object data = null;
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("X-Custom-Header", "application/json");
try {
// 獲取傳入數據
Object body = JSON.parseObject(JSONObject.toJSONString(input)).get("body");
if(body.toString().equals("<body><action>WARMUP</action></body>")){
this.timingTask();
warmNum++;
context.getLogger().log("啓動次數:"+warmNum);
return new GatewayResponse("{}",headers,200);
}
JSONObject requestDTO = JSON.parseObject(body.toString());
String requestMethod = requestDTO.getString("requestMethod");
String requestData = requestDTO.getString("requestData");
// 調用對應的方法
String serviceName = MethodCallEnums.getServiceNameByMethod(requestMethod);
String methodNameBymethod = MethodCallEnums.getMethodNameBymethod(requestMethod);
Class aClass = Class.forName(serviceName);
if (null == requestData || requestData.isEmpty()) {
try {
data = aClass.getMethod(methodNameBymethod).invoke(aClass.newInstance());
Result result = ResultUtil.success(data);
return new GatewayResponse(JSON.toJSONString(result),headers,200);
} catch (Exception e) {
e.printStackTrace();
Result result = ResultUtil.warn(ResultEnum.FAILED);
return new GatewayResponse(JSON.toJSONString(result),headers,500); }
} else {
try {
data = aClass.getMethod(methodNameBymethod, String.class).invoke(aClass.newInstance(), requestData);
Result result = ResultUtil.success(data);
return new GatewayResponse(JSON.toJSONString(result),headers,200);
} catch (IllegalAccessException e) {
e.printStackTrace();
Result result = ResultUtil.warn(ResultEnum.FAILED);
return new GatewayResponse(JSON.toJSONString(result),headers,500); }
}
} catch (Exception e) {
e.printStackTrace();
Result result = ResultUtil.warn(ResultEnum.FAILED);
return new GatewayResponse(JSON.toJSONString(result),headers,500);
}
}
以上是我寫的一個簡單的不能再簡單的lambda例子了,其中的要點我會稍微提一下,完整代碼戳這裏github傳送門下載。
要點
- lambda函數的入口是handleRequest()方法,用來處理請求
- Context對象是lambda上下文對象,可以將其封裝進日誌類裏打印日誌信息
- 請求體裏本例裏直接用父類Object接收,當然你也可以自定義接收對象和響應對象,但一定要包含必要的接收變量,比如body,headers,statusCode。
- 本例通過枚舉類和反射來處理路由
- 從請求獲取請求方法的方式有兩種:(1)從lambda請求裏的proxy獲取 (2)用戶在請求體body參數裏自定義,如本例中的requestMethod ,對於自定義的好處是,當需要配APIConfig的時候,可以一個模塊只配置一個API
- lambda可以結合aws自身的一些產品來使用,比如本例中的aws dynamodb和aws s3
- lambda可以處理get和post請求,根據請求方式不同相應處理即可
- 首次觸發時微服務冷啓動有些慢,但一旦啓動之後就可以用這個微服務實例接受後續的請求,只有在比較長的一段時間內未被觸發 AWS 纔會把這個微服務殺掉。
...
lambda還有很多其他的一些特性,這裏不一一提了。
寫在最後
AWS 的 Lambda 給了那些不想自己管理 EC2 服務器和配置負載人員很大的便利,所以 Lambda 被描述爲 Serverless。真正的只關注業務就行,怎麼調度,同時有多少個實例運行交給亞馬遜去處理就是了。運行 Lambda 的環境也是亞馬遜內部的 EC2 服務器,鏡像是 Amazon Linux, 所以如果想運行系統命令,那是 Linux 的。Lambda 支持多種語言 Node.js, Python, C#(.net core), 還有 Java 8,我們就選擇了 Java 8, 一開始還擔心它與別的語言比起來會多大劣勢,其實不然。而且所謂的 Java 8, 並非單指Java 語言,而是指 JVM 平臺,所以也可以用 Scala, Clojure, Groovy, Kotlin 來寫。
Java 與腳本語言如 Node.js, Python 相比給人一個明顯的感覺是啓動慢,還有人用統計數據來比劃AWS Lambda cold start(pseudeo-)benchmark.不過真不用擔心,人家說的是冷啓動,也就發生在部署後第一次執行啓動會比較慢。要是我們的 Lambda經常被調用,或每天觸發比較集中,Lambda 在任務到來之前處理待續狀態,就不會有冷啓動的耗時過程。或者是每次任務要執行 3分鐘左右,又何必在乎毫秒級的冷啓動時間。