最近接觸到了阿里云的函數計算的服務,經過幾天的嘗試還是有所收獲,因此不妨把學習過程中的點滴記錄下來,方便以后溫習。
什么是函數計算
根據阿里云的中的相關介紹,可以知道函數計算是事件驅動的全托管計算服務。用戶無需管理服務器等基礎設施,只需編寫代碼并上傳,函數計算會為您準備好計算資源,以彈性、可靠的方式運行您的代碼,并提供日志查詢、性能監控、報警等功能。從而實現了函數即服務。更多介紹可以參考阿里云函數計算
快速建立一個函數計算服務
新建項目并引入相關的依賴
在建立一個函數計算之前,首先要在阿里云開通函數計算的服務。阿里云函數計算目前支持Java(Java8),NodeJS(nodejs6,nodejs8),Python (Python2.7,Python3.6) 3種語言。本文主要詳細記錄Java環境下的搭建過程。
首先在IDEA中新建一個Maven項目,若在那個在代碼中正常使用函數計算,需要在pom.xml文件中加入對應的依賴:
<dependency>
<groupId>com.aliyun.fc.runtime</groupId>
<artifactId>fc-java-core</artifactId>
<version>1.0.0</version>
</dependency>
創建實現函數計算接口的類
正常導入依賴后,在java目錄下新建一個實現函數計算預定義接口的類FCController。函數計算目前有 2 個預定義的接口可以實現,StreamRequestHandler以及PojoRequestHandler。我們先以StreamRequestHandler舉例,查看StreamRequestHandler接口的代碼:
public interface StreamRequestHandler {
void handleRequest(InputStream var1, OutputStream var2, Context var3) throws IOException;
}
StreamRequestHandler接口只定義了一個無返回值的方法,輸入以及輸出均以流的方式實現,而context 是函數計算在運行時生成的一個包含一些運行時的信息對象。在FCController中重寫該方法:
package example;
import ...
public class FCController implements StreamRequestHandler{
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)throws IOException{
outputStream.write("Hello Function Compute".getBytes());
}
}
到目前為止,一個最簡單的函數計算的代碼已經編寫完成。
將代碼打包
我們在開發中通常會使用到自定義的模塊,因此在打jar包時需要將它們一起打包。Maven下可以通過使用maven-assembly-plugin 插件來進行打包。在pom.xml文件中加入如下代碼:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId> <!-- this is used for not append id to the jar name -->
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
然后使用mvn clean package進行打包。打包成功后在target文件夾下生成了可執行的jar包。
配置函數計算
jar包生成后,網頁打開阿里云函數計算控制臺,依照以下幾步完成函數計算的創建:
- 新建服務:填寫服務的名稱。
- 新建函數:函數模板下選擇語言環境,本例選擇Java8,選擇空白函數進入下一步。
- 觸發器配置:根據需要選擇觸發器。每個函數只可以配置一種觸發器。此處選擇了不設置觸發器。盡管如此,觸發器依然可以在后面進行添加。
- 基礎管理配置:填寫新建的函數名稱,注意選擇正確的運行環境。運行環境選擇Java后,下方會有進一步的配置,可以通過OSS或者直接上傳代碼包上傳代碼。直接上傳限制上傳文件的大小不得超過5M。環境配置中輸入正確的函數入口,依照"[package].[class]::[method]"的格式進行配置,如上文代碼中,包名為example,類名為FCController,方法名為handleRequest,因此函數入口應當為example.FCController::handleRequest 。
- 權限配置:此處跳過。
- 核對信息:最后核對配置的信息,無誤即可點擊創建。
執行函數計算
經過上述的步驟,函數計算已經可以成功創建。我們上傳的代碼包在執行之前,會被解壓縮,之后才會被加載,執行,因此不妨解壓生成的jar文件,看一下文件結構。我們可以看到在example文件下有編譯后的FCController.class文件,而文件的路徑符合之前填寫的函數入口。回到函數計算控制臺,點擊執行來執行我們上傳的程序并返回結果。
至此,一個最簡單的函數計算已經成功實現。
觸發器配置
在已經創建的函數界面可以看到如下四個窗口:
- 概覽 在概覽中可以對函數的屬性進行修改,例如我們在代碼中修改了類名,對應的函數入口也應當進行變更。
- 代碼執行 在代碼執行中可以執行已上傳的代碼,查看執行結果等。除此也可以上傳新的代碼包,注意上傳之后需要點擊保存才能是剛剛上傳的代碼包生效,否則函數計算執行的依然是之前的程序代碼。
- 觸發器 顯而易見,盡管之前沒有配置觸發器,我們依然可以在建立函數之后有選擇的創建。
- 日志查詢 在日志查詢中可以配置相關的日志查詢服務。
我們進入到觸發器窗口中,并且點擊創建觸發器,如圖:
關于觸發器的介紹可以參考阿里云關于觸發器
的相關介紹。值得一提的是,文檔在關于HTTP觸發器的介紹中寫道暫不支持HTTP觸發器,然而細心的可以在上圖中看到服務類型中含有HTTP觸發器,并且可以正常選中。選中之后填寫觸發器的相關信息。請求方法可以選擇多個。點擊創建后,發現已經添加了HTTP觸發器。
回到之前提及到的函數創建的觸發器配置步驟中,倘若在此處選擇HTTP觸發器,在下一步基礎配置管理中的運行環境下是無法選擇Java運行環境的。
創建好觸發器后,回到代碼執行窗口,可以看到界面多出來了一個調試HTTP觸發器。復制鏈接,在RestClient中實用Get方法請求,可以看到請求成功并且返回正確的結果。
很明顯,看我們不僅創建了文檔中所述的不支持Java運行環境的HTTP觸發器,并且驗證了創建的這個HTTP觸發器是可以正常使用的。因此,目前如果你想創建一個HTTP觸發器的Java運行環境的函數計算,切記在創建函數時選擇不創建觸發器,在函數創建成功后再添加HTTP觸發器。
函數計算進階
在實際開發中,我們的服務往往會接受一些參數,對這些參數或根據這些參數來進行下一步的代碼編寫,因此,Java寫的函數計算若要實現此功能需要實現PojoRequestHandler。PojoRequestHandler需要我們提供兩個Pojo類,分別用于輸入以及輸出。先上代碼:
@Data
public class Input {
private Integer num;
private String name;
private Boolean tag;
private List<Integer> integerList;
private Map<String,Integer> stringIntegerMap;
private Person person;
}
@Data
@Builder
public class Output {
private Integer length;
private String welcome;
private Boolean ifSuccess;
private List<Integer> integerList;
private Map<String, Integer> stringIntegerMap;
private Person person;
}
@Data
@AllArgsConstructor
public class Person {
private Integer age;
private String gender;
}
public class FCController implements PojoRequestHandler<Input, Output> {
@Override
public Output handleRequest(Input input, Context context){
return Output.builder()
.length(input.getIntegerList().size())
.welcome("Hello "+ input.getName())
.ifSuccess(!input.getTag())
.integerList(input.getIntegerList().stream().map(l -> l+2).collect(Collectors.toList()))
.stringIntegerMap(input.getStringIntegerMap())
.person(new Person(100,"female")).build();
}
public static void main(String[] args){}
}
Input類用于接收參數,定義了一些常用類型的屬性。Output類用于返回結果。FCController類實現了預定義的PojoRequestHandler接口,并重寫了handleRequest方法,接收Input類為輸入,并以Output類為輸出。打包后上傳函數計算控制臺,上傳后記得點擊保存保證計算使用最近更新的包。HTTP觸發器中請求選擇選擇POST方法,Body的row下填入要傳入的參數。例如:
{
"num": 10,
"name": "lwf",
"tag": false,
"integerList": [1, 2, 3, 4, 5, 6, 7],
"stringIntegerMap": {
"key": 10
},
"person": {
"age": 50,
"gender": "male"
}
}
點擊執行,返回結果。
到此我們已經實現了如何編寫代碼使得在函數計算下來接受參數值完成我們的業務。具體代碼見
GitHub
,target下的jar包可以直接上傳到函數計算中進行PojoRequestHandler的測試。
轉載請注明出處。