前言 首先介紹下在本文出現(xiàn)的幾個(gè)比較重要的概念:
函數(shù)計(jì)算(Function Compute): 函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的服務(wù),通過(guò)函數(shù)計(jì)算,用戶無(wú)需管理服務(wù)器等運(yùn)行情況,只需編寫代碼并上傳。函數(shù)計(jì)算準(zhǔn)備計(jì)算資源,并以彈性伸縮的方式運(yùn)行用戶代碼,而用戶只需根據(jù)實(shí)際代碼運(yùn)行所消耗的資源進(jìn)行付費(fèi)。函數(shù)計(jì)算更多信息 參考。
Fun: Fun 是一個(gè)用于支持 Serverless 應(yīng)用部署的工具,能幫助您便捷地管理函數(shù)計(jì)算、API 網(wǎng)關(guān)、日志服務(wù)等資源。它通過(guò)一個(gè)資源配置文件(template.yml),協(xié)助您進(jìn)行開(kāi)發(fā)、構(gòu)建、部署操作。Fun 的更多文檔 參考。
2.0 版本的 Fun,在部署這一塊做了很多努力,并提供了比較完善的功能,能夠做到將云資源方便、平滑地部署到云端。但該版本,在本地開(kāi)發(fā)上的體驗(yàn),還有較多的工作要做。于是,我們決定推出 Fun Local 彌補(bǔ)這一處短板。
Fun Local: Fun Local 作為 Fun 的一個(gè)子命令存在,只要 Fun 的版本大于等于 2.6.0,即可以直接通過(guò) fun local 命令使用。Fun Local 工具可以將函數(shù)計(jì)算中的函數(shù)在本地完全模擬運(yùn)行,并提供單步調(diào)試的功能,旨在彌補(bǔ)函數(shù)計(jì)算相對(duì)于傳統(tǒng)應(yīng)用開(kāi)發(fā)體驗(yàn)上的短板,并為用戶提供一種解決函數(shù)計(jì)算問(wèn)題排查的新途徑。
《開(kāi)發(fā)函數(shù)計(jì)算的正確姿勢(shì)》系列除本篇是為用戶介紹 fun local 的使用方法外,其他幾篇都會(huì)向用戶展示 Fun Local 對(duì)于函數(shù)計(jì)算開(kāi)發(fā)所帶來(lái)的效率上的巨大提升。
Fun Local 命令格式 使用 fun local invoke -h 可以查看 fun local invoke 的幫助信息:
$ fun local invoke -h Usage: invoke [options] <[service/]function>
Run your serverless application locally for quick development & testing.
Options:
-d, --debug-port <port> used for local debugging
-c, --config <ide> print out ide debug configuration. Options are VSCode
-e, --event <path> event file containing event data passed to the function
-h, --help output usage information
本地運(yùn)行函數(shù) 運(yùn)行函數(shù)的命令格式為:
fun local invoke [options] <[service/]function> 其中 options、service 都是可以省略的。 從調(diào)用方式上,可以理解為,fun local invoke 支持通過(guò) 函數(shù)名 調(diào)用,或者 服務(wù)名/函數(shù)名 的方式調(diào)用,即
fun local invoke function fun local invoke service/function 比如,如果要運(yùn)行名為 php72 的函數(shù),可以直接通過(guò)以下命令完成:
fun local invoke php72 調(diào)用結(jié)果為:

再比如,要運(yùn)行名為 nodejs8 的函數(shù),可以使用:
fun local invoke nodejs8 會(huì)得到如下結(jié)果:

如果 template.yml 中包含多個(gè)服務(wù),而多個(gè)服務(wù)中包含相同名稱的函數(shù)時(shí),通過(guò)函數(shù)名的方式調(diào)用 fun 只會(huì)運(yùn)行第一個(gè)名稱匹配的函數(shù)。
如果想要精準(zhǔn)匹配,可以使用 服務(wù)名/函數(shù)名 的方式。
比如想要調(diào)用 localdemo 下的 php72,可以使用:
fun local invoke localdemo/php72 在本例中,會(huì)得到和 fun local invoke php72 一致的結(jié)果。
以下是一個(gè)運(yùn)行 nodejs8 函數(shù)的演示:

本地運(yùn)行 java 類型的函數(shù) java 不同于解釋型的語(yǔ)言,在作為函數(shù)運(yùn)行前,需要先編譯。在我們的例子中,可以進(jìn)入到 demo 中的 java8 目錄,然后執(zhí)行:
mvn package 可以看到 log:
[INFO] skip non existing resourceDirectory /Users/tan/code/fun/examples/local/java8/src/test/resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ demo --- [INFO] No sources to compile [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ demo --- [INFO] No tests to run. [INFO] [INFO] --- maven-dependency-plugin:2.8:copy-dependencies (copy-dependencies) @ demo --- [INFO] fc-java-core-1.0.0.jar already exists in destination. [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ demo --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.223 s [INFO] Finished at: 2018-11-22T10:45:14 08:00 [INFO] Final Memory: 15M/309M [INFO] ------------------------------------------------------------------------ 該命令會(huì)在 java8/target 目錄下生成 demo-1.0-SNAPSHOT.jar 文件。
由于我們?cè)?template.yml 中配置的 CodeUri 為 java8/target/demo-1.0-SNAPSHOT.jar,因此不需要任何改動(dòng),可以直接通過(guò)以下命令運(yùn)行:
fun local invoke java8 運(yùn)行結(jié)果如下:

本地調(diào)試 fun local invoke 支持 -d, --debug-port <port> 選項(xiàng),可以對(duì)函數(shù)進(jìn)行本地單步調(diào)試。本文檔只介紹如何配置調(diào)試,并不涉及調(diào)試技巧,更多文章,請(qǐng)參考。
備注:Fun Local 涉及到的 debugging 技術(shù)全部都基于各個(gè)語(yǔ)言通用的調(diào)試協(xié)議實(shí)現(xiàn)的,因此無(wú)論什么語(yǔ)言的開(kāi)發(fā)者,即使不喜歡用 VSCode,只要使用對(duì)應(yīng)語(yǔ)言的 remote debugging 方法都可以進(jìn)行調(diào)試。
本地調(diào)試 nodejs、python 類型的函數(shù) 對(duì)于 nodejs6、nodejs8、python2.7、python3、java8 類型的函數(shù),調(diào)試方法基本一致。下面拿 nodejs8 舉例。
我們上面演示了可以通過(guò) fun local invoke nodejs8 來(lái)運(yùn)行名稱為 nodejs8 的函數(shù),如果想對(duì)該函數(shù)進(jìn)行調(diào)試,只需要使用 -d 參數(shù),并配置相應(yīng)的端口號(hào)即可。
比如我們以調(diào)試方式運(yùn)行函數(shù),并將調(diào)試端口設(shè)定在 3000,可以通過(guò)下面的命令:
fun local invoke -d 3000 nodejs8 另外,推薦添加 --config 參數(shù),在調(diào)試的同時(shí),可以輸出用來(lái)調(diào)試的 IDE 的配置信息:
fun local invoke -d 3000 --config VSCode nodejs8 命令執(zhí)行結(jié)果如下:
skip pulling images ... you can paste these config to .vscode/launch.json, and then attach to your running function ///////////////// config begin ///////////////// { "version": "0.2.0", "configurations": [ { "name": "fc/localdemo/nodejs8", "type": "node", "request": "attach", "address": "localhost", "port": 3000, "localRoot": "/Users/tan/code/fun/examples/local/nodejs8", "remoteRoot": "/code", "protocol": "inspect", "stopOnEntry": false } ] } ///////////////// config end ///////////////// Debugger listening on ws://0.0.0.0:3000/b65c288b-bd6a-4791-849b-b03e0d16b0ce For help see https:///en/docs/inspector 程序會(huì)阻塞在這里,并不會(huì)繼續(xù)往下執(zhí)行。只有 IDE 的連接上來(lái)后,程序才會(huì)繼續(xù)執(zhí)行。接下來(lái),我們針對(duì) VSCode 配置、VSCode 調(diào)試兩個(gè)方面分別進(jìn)行講解。
其中 VSCode 配置只有在第一次對(duì)函數(shù)進(jìn)行調(diào)試時(shí)才需要,如果已經(jīng)配置過(guò),則不需要再次配置。
VSCode 配置 創(chuàng)建 vscode launch.json 文件
 復(fù)制日志中的 config begin 與 config end 之間的配置到 launch.json 中。
 完成上面配置后,在 Debug 視圖可以看到配置的函數(shù)列表。
 至此,VSCode 配置完成。VSCode 更多配置知識(shí)可以參考官方文檔。
VSCode 調(diào)試 VSCode 配置成功后,只需要在 VSCode 編輯器側(cè)邊欄單擊設(shè)置斷點(diǎn),然后點(diǎn)擊“開(kāi)始調(diào)試”按鈕,即可開(kāi)始調(diào)試。

本地調(diào)試 java 類型的函數(shù) 調(diào)試 java 函數(shù)的過(guò)程和 nodejs、python 是類似的。但由于 java 程序員通常喜歡用 IDEA、Eclipse 這樣的 IDE,所以我們單獨(dú)拿出來(lái)說(shuō)一下。
使用 VSCode 調(diào)試 java 使用 VSCode 調(diào)試 java 時(shí),需要安裝兩個(gè)插件:Language Support for Java(TM) by Red Hat、Debugger for Java。利用 VSCode 的插件市場(chǎng)安裝插件很簡(jiǎn)單,可以 參考。
使用 IDEA 調(diào)試 java IDEA 配置 IDEA 配置 remote debugging 還是比較簡(jiǎn)單的,首先在菜單欄依次點(diǎn)擊 Run -> Edit Configurations...:

然后新建一個(gè) Remote Debugging:

然后我們隨意輸出一個(gè)名字,并配置端口號(hào)為 3000.

以下是一個(gè)配置 IDEA remote debugging 的完整流程演示:

使用 IDEA 開(kāi)始調(diào)試 首先將 java 函數(shù)以 debug 的方式運(yùn)行起來(lái):
fun local invoke -d 3000 java8

可以看到函數(shù)卡在這里了,接著我們使用 IDEA 連接并開(kāi)始調(diào)試??梢酝ㄟ^(guò)菜單欄上的 Run -> Debug... 或者工具欄直接點(diǎn)擊 Debug 按鈕,即可開(kāi)始調(diào)試。
以下是一個(gè)用 IDEA 進(jìn)行 remote debugging 的完整流程演示:

本地調(diào)試 php 類型的函數(shù) php 的調(diào)試與其他類型的函數(shù)調(diào)試在流程上有一些不同。
首先,php 的運(yùn)行通過(guò) fun local invoke php72 命令完成,這與其他類型的函數(shù)一致。調(diào)試時(shí),也像其他類型的函數(shù)一樣,通過(guò) -d 參數(shù)以調(diào)試模式啟動(dòng)函數(shù):
fun local invoke -d 3000 --config VSCode php72 但不同的是,以 debug 方式運(yùn)行 php 函數(shù)后,php 函數(shù)并沒(méi)有阻塞等待 vscode 調(diào)試器的連接,而是直接運(yùn)行結(jié)束。
skip pulling images ... you can paste these config to .vscode/launch.json, and then attach to your running function ///////////////// config begin ///////////////// { "version": "0.2.0", "configurations": [ { "name": "fc/localdemo/php72", "type": "php", "request": "launch", "port": 3000, "stopOnEntry": false, "pathMappings": { "/code": "/Users/tan/code/fun/examples/local/php7.2" }, "ignore": [ "/var/fc/runtime/**" ] } ] } ///////////////// config end ///////////////// FunctionCompute php7.2 runtime inited. FC Invoke Start RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4 FC Invoke End RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4 hello world
RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4 Billed Duration: 48 ms Memory Size: 1998 MB Max Memory Used: 58 MB 這是因?yàn)?,?duì)于 php 程序,需要首先啟動(dòng) vscode 的調(diào)試器。
php 類型的函數(shù)啟動(dòng) VSCode 調(diào)試器的流程與其他類型的函數(shù)一致:復(fù)制上面日志中的 vscode 配置到 launch.json,單擊“開(kāi)始調(diào)試”即可。
然后在終端重新以調(diào)試模式啟動(dòng) php 函數(shù)即可開(kāi)始調(diào)試:
fun local invoke -d 3000 php72

Event 事件源 函數(shù)計(jì)算提供了豐富的觸發(fā)器,包括但不局限于對(duì)象存儲(chǔ)觸發(fā)器、日志服務(wù)觸發(fā)器、CDN 事件觸發(fā)器等。在本地?zé)o論是運(yùn)行還是調(diào)試函數(shù)時(shí),為了能夠完全模擬線上環(huán)境,通常需要構(gòu)造觸發(fā)事件。
觸發(fā)事件可以是一段可讀的 json 配置,也可以是一段非可讀的二進(jìn)制數(shù)據(jù)。這里我們拿 json 舉例,假設(shè)觸發(fā)事件內(nèi)容為:
{ "testKey": "testValue" } 想要將這段事件內(nèi)容傳給函數(shù),可以通過(guò)以下三種途徑:
管道: echo '{"testKey": "testValue"}' | fun local invoke nodejs8 文件: 將的 json 內(nèi)容寫入到文件,文件名隨意,比如 event.json。然后通過(guò) -e 指定文件名:fun local invoke -e event.json nodejs8 重定向: fun local invoke nodejs8 < event.json 或者 fun local invoke nodejs8 <<< '{"testKey": "testValue"}' 等等。更多信息可以參考這篇文章。 環(huán)境變量 在 template.yml 中配置的 EnvironmentVariables 會(huì)與線上行為一致,當(dāng)函數(shù)運(yùn)行時(shí),可以通過(guò)代碼獲取到。更多信息參考。
在本地運(yùn)行函數(shù)時(shí),除了 EnvironmentVariables 配置的環(huán)境變量,fun 還會(huì)額外提供一個(gè) local=true 的環(huán)境變量,用來(lái)標(biāo)識(shí)這是一個(gè)本地運(yùn)行的函數(shù)。
通過(guò)這個(gè)環(huán)境變量,用戶可以區(qū)分是本地運(yùn)行還是線上運(yùn)行,以便于進(jìn)行一些特定的邏輯處理。
Initializer 在 template.yml 中配置的 Initializer 屬性會(huì)與線上行為一致,當(dāng)函數(shù)運(yùn)行時(shí),會(huì)首先運(yùn)行 Initializer 指定的方法。Initializer 更多信息 參考。
Credentials 用戶可以通過(guò) Credentials 中存儲(chǔ)的 ak 信息訪問(wèn)阿里云的其他服務(wù)。Fun local 在本地運(yùn)行函數(shù)時(shí),會(huì)按照與 fun deploy 相同的 策略 尋找 ak 信息。
關(guān)于函數(shù)計(jì)算 Credentials 的描述,可以參考。
以下是一個(gè)根據(jù)本地、線上環(huán)境的不同,利用函數(shù)提供的 Credentials 配置 oss client 的例子:
local = bool(os.getenv('local', "")) if (local): print 'thank you for running function in local!!!!!!' auth = oss2.Auth(creds.access_key_id, creds.access_key_secret) else: auth = oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds.security_token) 附錄
代碼 本文講解涉及到的 demo 代碼,托管在 github 上。項(xiàng)目目錄結(jié)構(gòu)如下:
. ├── java8 │ ├── pom.xml │ ├── src │ │ └── main │ │ └── java │ │ └── example │ │ └── App.java │ └── target │ └── demo-1.0-SNAPSHOT.jar ├── nodejs6 │ └── index.js ├── nodejs8 │ └── index.js ├── php7.2 │ └── index.php ├── python2.7 │ └── index.py ├── python3 │ └── index.py └── template.yml template.yml 定義了函數(shù)計(jì)算模型,其中定義了一個(gè)名為 localdemo 的服務(wù),并在該服務(wù)下,定義了 6 個(gè)函數(shù),名稱分別是 nodejs6、nodejs8、php72、python27、python3、java8。它們對(duì)應(yīng)的代碼目錄由 template 中的 CodeUri 定義,分別位于 nodejs6、nodejs8、php7.2、python2.7、python3、java8 目錄。
更多參考 Fun Repo Fun specs Fun examples Fun 發(fā)布 2.0 新版本啦 函數(shù)計(jì)算工具鏈新成員 —— Fun Local 發(fā)布啦 來(lái)源:http://www./content-4-91901.html
|