最近接觸到了阿里云的函數(shù)計(jì)算的服務(wù),經(jīng)過(guò)幾天的嘗試還是有所收獲,因此不妨把學(xué)習(xí)過(guò)程中的點(diǎn)滴記錄下來(lái),方便以后溫習(xí)帚桩。
什么是函數(shù)計(jì)算
根據(jù)阿里云的中的相關(guān)介紹,可以知道函數(shù)計(jì)算是事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)嘹黔。用戶(hù)無(wú)需管理服務(wù)器等基礎(chǔ)設(shè)施账嚎,只需編寫(xiě)代碼并上傳,函數(shù)計(jì)算會(huì)為您準(zhǔn)備好計(jì)算資源,以彈性郭蕉、可靠的方式運(yùn)行您的代碼乏悄,并提供日志查詢(xún)、性能監(jiān)控恳不、報(bào)警等功能。從而實(shí)現(xiàn)了函數(shù)即服務(wù)开呐。更多介紹可以參考阿里云函數(shù)計(jì)算
快速建立一個(gè)函數(shù)計(jì)算服務(wù)
新建項(xiàng)目并引入相關(guān)的依賴(lài)
在建立一個(gè)函數(shù)計(jì)算之前烟勋,首先要在阿里云開(kāi)通函數(shù)計(jì)算的服務(wù)。阿里云函數(shù)計(jì)算目前支持Java(Java8)筐付,NodeJS(nodejs6卵惦,nodejs8),Python (Python2.7瓦戚,Python3.6) 3種語(yǔ)言沮尿。本文主要詳細(xì)記錄Java環(huán)境下的搭建過(guò)程。
首先在IDEA中新建一個(gè)Maven項(xiàng)目较解,若在那個(gè)在代碼中正常使用函數(shù)計(jì)算畜疾,需要在pom.xml文件中加入對(duì)應(yīng)的依賴(lài):
<dependency>
<groupId>com.aliyun.fc.runtime</groupId>
<artifactId>fc-java-core</artifactId>
<version>1.0.0</version>
</dependency>
創(chuàng)建實(shí)現(xiàn)函數(shù)計(jì)算接口的類(lèi)
正常導(dǎo)入依賴(lài)后,在java目錄下新建一個(gè)實(shí)現(xiàn)函數(shù)計(jì)算預(yù)定義接口的類(lèi)FCController印衔。函數(shù)計(jì)算目前有 2 個(gè)預(yù)定義的接口可以實(shí)現(xiàn)啡捶,StreamRequestHandler以及PojoRequestHandler。我們先以StreamRequestHandler舉例奸焙,查看StreamRequestHandler接口的代碼:
public interface StreamRequestHandler {
void handleRequest(InputStream var1, OutputStream var2, Context var3) throws IOException;
}
StreamRequestHandler接口只定義了一個(gè)無(wú)返回值的方法瞎暑,輸入以及輸出均以流的方式實(shí)現(xiàn),而context 是函數(shù)計(jì)算在運(yùn)行時(shí)生成的一個(gè)包含一些運(yùn)行時(shí)的信息對(duì)象与帆。在FCController中重寫(xiě)該方法:
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());
}
}
到目前為止了赌,一個(gè)最簡(jiǎn)單的函數(shù)計(jì)算的代碼已經(jīng)編寫(xiě)完成。
將代碼打包
我們?cè)陂_(kāi)發(fā)中通常會(huì)使用到自定義的模塊玄糟,因此在打jar包時(shí)需要將它們一起打包勿她。Maven下可以通過(guò)使用maven-assembly-plugin 插件來(lái)進(jìn)行打包。在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進(jìn)行打包茶凳。打包成功后在target文件夾下生成了可執(zhí)行的jar包嫂拴。
配置函數(shù)計(jì)算
jar包生成后,網(wǎng)頁(yè)打開(kāi)阿里云函數(shù)計(jì)算控制臺(tái)贮喧,依照以下幾步完成函數(shù)計(jì)算的創(chuàng)建:
- 新建服務(wù):填寫(xiě)服務(wù)的名稱(chēng)筒狠。
- 新建函數(shù):函數(shù)模板下選擇語(yǔ)言環(huán)境,本例選擇Java8箱沦,選擇空白函數(shù)進(jìn)入下一步辩恼。
- 觸發(fā)器配置:根據(jù)需要選擇觸發(fā)器。每個(gè)函數(shù)只可以配置一種觸發(fā)器。此處選擇了不設(shè)置觸發(fā)器灶伊。盡管如此疆前,觸發(fā)器依然可以在后面進(jìn)行添加。
- 基礎(chǔ)管理配置:填寫(xiě)新建的函數(shù)名稱(chēng)聘萨,注意選擇正確的運(yùn)行環(huán)境竹椒。運(yùn)行環(huán)境選擇Java后,下方會(huì)有進(jìn)一步的配置米辐,可以通過(guò)OSS或者直接上傳代碼包上傳代碼胸完。直接上傳限制上傳文件的大小不得超過(guò)5M。環(huán)境配置中輸入正確的函數(shù)入口翘贮,依照"[package].[class]::[method]"的格式進(jìn)行配置赊窥,如上文代碼中,包名為example狸页,類(lèi)名為FCController锨能,方法名為handleRequest,因此函數(shù)入口應(yīng)當(dāng)為example.FCController::handleRequest 芍耘。
- 權(quán)限配置:此處跳過(guò)址遇。
- 核對(duì)信息:最后核對(duì)配置的信息,無(wú)誤即可點(diǎn)擊創(chuàng)建。
執(zhí)行函數(shù)計(jì)算
經(jīng)過(guò)上述的步驟斋竞,函數(shù)計(jì)算已經(jīng)可以成功創(chuàng)建傲隶。我們上傳的代碼包在執(zhí)行之前,會(huì)被解壓縮窃页,之后才會(huì)被加載跺株,執(zhí)行,因此不妨解壓生成的jar文件脖卖,看一下文件結(jié)構(gòu)乒省。我們可以看到在example文件下有編譯后的FCController.class文件,而文件的路徑符合之前填寫(xiě)的函數(shù)入口畦木⌒淇福回到函數(shù)計(jì)算控制臺(tái),點(diǎn)擊執(zhí)行來(lái)執(zhí)行我們上傳的程序并返回結(jié)果十籍。
至此蛆封,一個(gè)最簡(jiǎn)單的函數(shù)計(jì)算已經(jīng)成功實(shí)現(xiàn)。
觸發(fā)器配置
在已經(jīng)創(chuàng)建的函數(shù)界面可以看到如下四個(gè)窗口:
- 概覽 在概覽中可以對(duì)函數(shù)的屬性進(jìn)行修改勾栗,例如我們?cè)诖a中修改了類(lèi)名惨篱,對(duì)應(yīng)的函數(shù)入口也應(yīng)當(dāng)進(jìn)行變更。
- 代碼執(zhí)行 在代碼執(zhí)行中可以執(zhí)行已上傳的代碼围俘,查看執(zhí)行結(jié)果等砸讳。除此也可以上傳新的代碼包琢融,注意上傳之后需要點(diǎn)擊保存才能是剛剛上傳的代碼包生效,否則函數(shù)計(jì)算執(zhí)行的依然是之前的程序代碼簿寂。
- 觸發(fā)器 顯而易見(jiàn)漾抬,盡管之前沒(méi)有配置觸發(fā)器,我們依然可以在建立函數(shù)之后有選擇的創(chuàng)建常遂。
- 日志查詢(xún) 在日志查詢(xún)中可以配置相關(guān)的日志查詢(xún)服務(wù)纳令。
我們進(jìn)入到觸發(fā)器窗口中,并且點(diǎn)擊創(chuàng)建觸發(fā)器克胳,如圖:
關(guān)于觸發(fā)器的介紹可以參考阿里云關(guān)于觸發(fā)器
的相關(guān)介紹泊碑。值得一提的是,文檔在關(guān)于HTTP觸發(fā)器的介紹中寫(xiě)道暫不支持HTTP觸發(fā)器毯欣,然而細(xì)心的可以在上圖中看到服務(wù)類(lèi)型中含有HTTP觸發(fā)器,并且可以正常選中臭脓。選中之后填寫(xiě)觸發(fā)器的相關(guān)信息酗钞。請(qǐng)求方法可以選擇多個(gè)。點(diǎn)擊創(chuàng)建后来累,發(fā)現(xiàn)已經(jīng)添加了HTTP觸發(fā)器砚作。
回到之前提及到的函數(shù)創(chuàng)建的觸發(fā)器配置步驟中,倘若在此處選擇HTTP觸發(fā)器嘹锁,在下一步基礎(chǔ)配置管理中的運(yùn)行環(huán)境下是無(wú)法選擇Java運(yùn)行環(huán)境的葫录。
創(chuàng)建好觸發(fā)器后,回到代碼執(zhí)行窗口领猾,可以看到界面多出來(lái)了一個(gè)調(diào)試HTTP觸發(fā)器米同。復(fù)制鏈接,在RestClient中實(shí)用Get方法請(qǐng)求派阱,可以看到請(qǐng)求成功并且返回正確的結(jié)果矗漾。
很明顯榕吼,看我們不僅創(chuàng)建了文檔中所述的不支持Java運(yùn)行環(huán)境的HTTP觸發(fā)器,并且驗(yàn)證了創(chuàng)建的這個(gè)HTTP觸發(fā)器是可以正常使用的熬苍。因此,目前如果你想創(chuàng)建一個(gè)HTTP觸發(fā)器的Java運(yùn)行環(huán)境的函數(shù)計(jì)算袁翁,切記在創(chuàng)建函數(shù)時(shí)選擇不創(chuàng)建觸發(fā)器柴底,在函數(shù)創(chuàng)建成功后再添加HTTP觸發(fā)器。
函數(shù)計(jì)算進(jìn)階
在實(shí)際開(kāi)發(fā)中粱胜,我們的服務(wù)往往會(huì)接受一些參數(shù)柄驻,對(duì)這些參數(shù)或根據(jù)這些參數(shù)來(lái)進(jìn)行下一步的代碼編寫(xiě),因此焙压,Java寫(xiě)的函數(shù)計(jì)算若要實(shí)現(xiàn)此功能需要實(shí)現(xiàn)PojoRequestHandler凿歼。PojoRequestHandler需要我們提供兩個(gè)Pojo類(lèi)褪迟,分別用于輸入以及輸出。先上代碼:
@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類(lèi)用于接收參數(shù)答憔,定義了一些常用類(lèi)型的屬性味赃。Output類(lèi)用于返回結(jié)果。FCController類(lèi)實(shí)現(xiàn)了預(yù)定義的PojoRequestHandler接口虐拓,并重寫(xiě)了handleRequest方法心俗,接收Input類(lèi)為輸入,并以O(shè)utput類(lèi)為輸出蓉驹。打包后上傳函數(shù)計(jì)算控制臺(tái)城榛,上傳后記得點(diǎn)擊保存保證計(jì)算使用最近更新的包。HTTP觸發(fā)器中請(qǐng)求選擇選擇POST方法态兴,Body的row下填入要傳入的參數(shù)狠持。例如:
{
"num": 10,
"name": "lwf",
"tag": false,
"integerList": [1, 2, 3, 4, 5, 6, 7],
"stringIntegerMap": {
"key": 10
},
"person": {
"age": 50,
"gender": "male"
}
}
點(diǎn)擊執(zhí)行,返回結(jié)果瞻润。
到此我們已經(jīng)實(shí)現(xiàn)了如何編寫(xiě)代碼使得在函數(shù)計(jì)算下來(lái)接受參數(shù)值完成我們的業(yè)務(wù)喘垂。具體代碼見(jiàn)
GitHub
,target下的jar包可以直接上傳到函數(shù)計(jì)算中進(jìn)行PojoRequestHandler的測(cè)試绍撞。
轉(zhuǎn)載請(qǐng)注明出處正勒。