使用Lambda和API網關在Java中開發RESTful微服務

本文爲翻譯發表,轉載需要註明來自公衆號EAWorld。

作者:Muhammad Ali

譯者:白小白

原題:Developing RESTful APIs in Java using Amazon APIGateway and AWS Lambda

全文2294字,閱讀約需要10分鐘

白小白:

記得之前有一位兄弟說過,寫代碼的同學最恨的就是按照一個教程一步步做,結果卡在那裏做不下去。保險起見,作爲Java零基礎的小白對本文的實例進行了驗證。一些遇到卡殼的地方,以註釋的形式對原文進行了補充,當然,相關異常也可能不出現,那說明你臉比較白,自然要恭喜。小白的驗證的環境如下:Win10(64位)+Eclipse(Photon)+JavaSE8(64位)。全文的實踐要在兩個環境中進行,一是Eclipse客戶端(本地),一是在AWS的控制檯(遠程/瀏覽器訪問 https://console.aws.amazon.com/console/home )。

導言

AWS Lambda和AmazonAPI-Gateway可用於在Java中創建RESTfulWeb服務,而無需進行復雜的Java框架配置或設置和維護Web服務器(如Tomcat、WebSphere等)。Lambda和APIGateway的結合使得開發API變得非常容易,並且還可以輕鬆地管理API的暫存環境,比如開發、測試和Prod。

AWS Lambda是一個高度可伸縮和高度可用的無服務器計算平臺,您可以使用它運行Java代碼來提供服務的主要功能。有關Lambda的更多信息,請訪問鏈接

(https://aws.amazon.com/documentation/lambda/).

AmazonAPI網關是由AWS提供的一種網絡服務,允許開發人員輕鬆地構建和部署API端點。它使開發人員非常容易地創建HTTPS端點並將其與Lambda函數集成。數據從API端點傳遞到Lambda函數,並由API網關處理。欲瞭解更多關於API網關的內容,請訪問鏈接

(https://aws.amazon.com/documentation/apigateway/).

本文提供了關於如何使用Lambda和API網關在Java中開發RESTful微服務的循序漸進的指南。

先決條件

首先,您需要準備一臺開發機器,爲此您需要Java 8、Eclipse IDE和AWSToolkit for Eclipse。有關如何完成此操作的詳細信息,請參閱

(https://www.bluestackcloud.com/insights/2018/5/7/getting-started-with-aws-development-using-java).

白小白:

如果Marketplace閃退,在Eclipse的 Help –> Install New Software,通過在Work with處輸入 http://download.eclipse.org/mpc/photon/重新安裝。注意,在後續步驟有一個安裝組件選擇的勾選列表,如果本機沒有安裝RDS數據庫,把關於RDS這一項勾選去掉,否則後續步驟會報錯。

步驟1:(環境:Eclipse本地)創建Lambda函數

1. 一旦您準備好使用Eclipse IDE,AWS圖標將出現在主工具欄中。點擊它並選擇“新AWS Lambda項目.”

2.提供適當的項目名稱和Maven配置。選擇“Stream Request Handler”作爲輸入類型。

3. 在點擊“Finish”之後,示例代碼將被加載到您新創建的項目中。打開主處理程序函數並更新以下代碼。

package com.amazonaws.lambda.demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.Writer;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;

public class LambdaFunctionHandler implements RequestStreamHandler
{
JSONParser parser = new JSONParser();

  @Override
  public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException
  {
    LambdaLogger logger = context.getLogger();
      logger.log("Loading Java Lambda handler of ProxyWithStream");
      
      String proxy = null;
String param1 = null;
String param2 = null;

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
      JSONObject responseJson = new JSONObject();
      String responseCode = "200";
      JSONObject event = null;
      
      try {
        event = (JSONObject)parser.parse(reader);
        if (event.get("pathParameters") != null) {
          JSONObject pps = (JSONObject)event.get("pathParameters");
          if ( pps.get("proxy") != null) {
            proxy = (String)pps.get("proxy");
          }      
        }
        if (event.get("queryStringParameters") != null)
        {
          JSONObject qps = (JSONObject)event.get("queryStringParameters");
          if ( qps.get("param1") != null)
          {
            param1 = (String)qps.get("param1");
          }
        }
        if (event.get("queryStringParameters") != null)
        {
          JSONObject qps = (JSONObject)event.get("queryStringParameters");
          if ( qps.get("param2") != null)
          {
            param2 = (String)qps.get("param2");
          }
        }
        
      }
      catch(Exception pex)
      {
        responseJson.put("statusCode", "400");
        responseJson.put("exception", pex);
      }
        // Implement your logic here
       int output = 0;
       if (proxy.equals("sum"))
       {
         output = sum(Integer.parseInt(param1), Integer.parseInt(param2));
       }
       else if (proxy.equals("subtract"))
       {
         output = subtract(Integer.parseInt(param1), Integer.parseInt(param2));
       }
       
       JSONObject responseBody = new JSONObject();
         responseBody.put("input", event.toJSONString());
         responseBody.put("message", "Output is" + output);
         
         JSONObject headerJson = new JSONObject();
         headerJson.put("x-custom-header", "my custom header value");
         headerJson.put("Access-Control-Allow-Origin", "*");
         
         responseJson.put("isBase64Encoded", false);
         responseJson.put("statusCode", responseCode);
         responseJson.put("headers", headerJson);
         responseJson.put("body", responseBody.toString());
         
         OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
         writer.write(responseJson.toJSONString());
         writer.close();
        
  }
  public int sum(int a, int b)
  {
    return a+b;
  }
  public int subtract(int a, int b)
  {
    return a-b;
  }
}

(左右滑動可查看全部代碼)

白小白:

首先是代碼中的類名,需要修改爲第2步中的Class name,。其次是可能會遇到JSON無法解析的錯誤。需要下載JSON的包然後引入項目。引入的方法是將JSON包下載到本地,然後在項目上右鍵 –> Build Path –> Add External Achives 選擇本地包添加即可。JSON包的下載地址(http://www.java2s.com/Code/JarDownload/json-simple/json-simple-1.1.jar.zip)。如果遇到 Fatal error compiling: tools.jar not found 的報錯,從Eclipse菜單中選擇 Windows -> Preferences -> Java -> Installed JREs –> Execution Environment -> JavaSE1.x -> JDE 1.x 勾選即可。至於那個.x,我選擇的是最低版本號1.6

4. 構建並部署此Lambda函數。有關部署Java Lambda函數的完整信息可以找到這裏

(https://docs.aws.amazon.com/lambda/latest/dg/java-create-jar-pkg-maven-and-eclipse.html).

白小白:

構建部署的方法其實很簡單,就是在項目上右鍵 –> Amazon Web Services –> Upload function to AWS Lambda。但是前提是你需要有一個AWS的賬號,並需要提供給Eclipse客戶端一個Access Key ID和Secret Access Key。這需要你在AWS的控制檯創建一個用戶,併爲用戶添加 AdministratorAccess 權限,創建過程中可得到這兩個值。但要及時保存,否則在創建後,Secret Access Key是不可見的,除非在安全證書頁面重新創建訪問密鑰。上傳函數的過程,可能會有部分輸入框提示not found,此時只需要點擊其右側的create即可。

在這個例子中,我們用“REST_API_HelloWorld”的名稱在AWS控制檯中創建了Lambda函數。

步驟2:(環境:AWS控制檯/網頁)創建API網關端點

1.轉到AWS控制檯並啓動API-網關服務。

2.點擊“創建API”。

3.選擇“新API”並提供“API名稱”

4.在創建API之後,添加一個資源,如下所示:

5. 確保勾選“配置爲代理資源”選項。

在下一個顯示“Any”方法設置的屏幕上,選擇“Lambda Function”作爲集成類型。同時選中“Use Lambda Proxy integration”。選擇部署Lambda函數的區域,並輸入Lambda名稱。

白小白:

上面的Lambda Function輸入框,可以輸入剛纔上傳的函數名稱,會出現下拉列表選擇。在下一個部署API的步驟前,其實已經可以測試API是否可以正常工作,即點擊 資源 - ANY 再點擊測試,方法選擇GET ,在 路徑 處輸入 sum ,在查詢字串處輸入 param1=100&param2=100 ,點擊測試,在右側的響應正文部分,message的值應該爲 "Output is 200"。如果很不幸,測試不成功,右側顯示的錯誤是:Malformed Lambda proxy response (正如第一次部署時小白所遇到的情況),可以嘗試以下方法:1、確認第4步中的Enable API Gateway CORS是否已經勾選。;2、在代碼中註釋掉 headerJson.put("Access-Control-Allow-Origin", "*"); 這句話。

6.現在,我們將把這個API部署到一個暫存環境中。爲此,單擊“Action”並選擇“Deploy API”。

7.選擇[NewStage]並提供一個staging名稱和描述。在本教程中,我們使用“Dev”作爲名稱。一旦部署完成,控制檯將帶您到staging頁。

8.複製“Invoke URL”,並在其上添加代理資源名稱和參數,其中包含要發送給Lambda的值。有關本教程,請參閱下面的示例:

  • 格式:https://5yv20hbz44.execute-api.eu-west-1.amazonaws.com/Dev/{proxy}?{set_of_params_separated_by_&}
  • 示例:https://5yv20hbz44.execute-api.eu-west-1.amazonaws.com/Dev/sum?param1=100&param2=100

輸出如下:

結語

像AWS Lambda這樣的無服務器計算平臺最近非常流行。許多組織要求他們的DevOps工程師能夠開發無服務器應用程序,因爲它減少了設置硬件/軟件基礎結構所需的時間,從而減少了項目交付時間。遵循這個簡單的教程,您應該能夠開始使用Java在AWS上開發無服務器的微服務。

白小白:

爲了避免破壞原文的結構,小白的補充內容都是沒有添加截圖的,如果有什麼地方沒說明白,大家可以關注公衆號 EAWorld 戳 “加羣”,然後在羣內提問,只要是我遇到過的問題,我會再作進一步的解釋。

原文鏈接:

https://www.bluestackcloud.com/insights/2018/6/14/developing-restful-apis-in-java-using-amazon-api-gateway-and-aws-lambda

關於作者:Muhammad Ali,DevOps Engineer,BluestackCloud

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章