首先介紹下在本文出現的幾個比較重要的概念:php
函數計算(Function Compute): 函數計算是一個事件驅動的服務,經過函數計算,用戶無需管理服務器等運行狀況,只需編寫代碼並上傳。函數計算準備計算資源,並以彈性伸縮的方式運行用戶代碼,而用戶只需根據實際代碼運行所消耗的資源進行付費。函數計算更多信息 參考。html
Fun: Fun 是一個用於支持 Serverless 應用部署的工具,能幫助您便捷地管理函數計算、API 網關、日誌服務等資源。它經過一個資源配置文件(template.yml),協助您進行開發、構建、部署操做。Fun 的更多文檔 參考。java
2.0 版本的 Fun,在部署這一塊作了不少努力,並提供了比較完善的功能,可以作到將雲資源方便、平滑地部署到雲端。但該版本,在本地開發上的體驗,還有較多的工做要作。因而,咱們決定推出 Fun Local 彌補這一處短板。node
Fun Local: Fun Local 做爲 Fun 的一個子命令存在,只要 Fun 的版本大於等於 2.6.0,便可以直接經過
fun local
命令使用。Fun Local 工具能夠將函數計算中的函數在本地徹底模擬運行,並提供單步調試的功能,旨在彌補函數計算相對於傳統應用開發體驗上的短板,併爲用戶提供一種解決函數計算問題排查的新途徑。python
《開發函數計算的正確姿式》系列除本篇是爲用戶介紹 fun local 的使用方法外,其餘幾篇都會向用戶展現 Fun Local 對於函數計算開發所帶來的效率上的巨大提高。linux
使用 fun local invoke -h
能夠查看 fun local invoke 的幫助信息:git
$ 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
運行函數的命令格式爲:程序員
fun local invoke [options] <[service/]function>
其中 options、service 都是能夠省略的。
從調用方式上,能夠理解爲,fun local invoke 支持經過 函數名
調用,或者 服務名/函數名
的方式調用,即github
fun local invoke function fun local invoke service/function
好比,若是要運行名爲 php72 的函數,能夠直接經過如下命令完成:json
fun local invoke php72
調用結果爲:
再好比,要運行名爲 nodejs8 的函數,可使用:
fun local invoke nodejs8
會獲得以下結果:
若是 template.yml 中包含多個服務,而多個服務中包含相同名稱的函數時,經過函數名的方式調用 fun 只會運行第一個名稱匹配的函數。
若是想要精準匹配,可使用 服務名/函數名
的方式。
好比想要調用 localdemo 下的 php72,可使用:
fun local invoke localdemo/php72
在本例中,會獲得和 fun local invoke php72
一致的結果。
如下是一個運行 nodejs8 函數的演示:
java 不一樣於解釋型的語言,在做爲函數運行前,須要先編譯。在咱們的例子中,能夠進入到 demo 中的 java8 目錄,而後執行:
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] ------------------------------------------------------------------------
該命令會在 java8/target 目錄下生成 demo-1.0-SNAPSHOT.jar 文件。
因爲咱們在 template.yml 中配置的 CodeUri 爲 java8/target/demo-1.0-SNAPSHOT.jar,所以不須要任何改動,能夠直接經過如下命令運行:
fun local invoke java8
運行結果以下:
如下是一個運行 java8 函數的演示:
fun local invoke 支持 -d, --debug-port <port>
選項,能夠對函數進行本地單步調試。本文檔只介紹如何配置調試,並不涉及調試技巧,更多文章,請參考。
備註:Fun Local 涉及到的 debugging 技術所有都基於各個語言通用的調試協議實現的,所以不管什麼語言的開發者,即便不喜歡用 VSCode,只要使用對應語言的 remote debugging 方法均可以進行調試。
對於 nodejs六、nodejs八、python2.七、python三、java8 類型的函數,調試方法基本一致。下面拿 nodejs8 舉例。
咱們上面演示了能夠經過 fun local invoke nodejs8
來運行名稱爲 nodejs8 的函數,若是想對該函數進行調試,只須要使用 -d 參數,並配置相應的端口號便可。
好比咱們以調試方式運行函數,並將調試端口設定在 3000,能夠經過下面的命令:
fun local invoke -d 3000 nodejs8
另外,推薦添加 --config 參數,在調試的同時,能夠輸出用來調試的 IDE 的配置信息:
fun local invoke -d 3000 --config VSCode nodejs8
命令執行結果以下:
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://nodejs.org/en/docs/inspector
程序會阻塞在這裏,並不會繼續往下執行。只有 IDE 的鏈接上來後,程序纔會繼續執行。接下來,咱們針對 VSCode 配置、VSCode 調試兩個方面分別進行講解。
其中 VSCode 配置只有在第一次對函數進行調試時才須要,若是已經配置過,則不須要再次配置。
至此,VSCode 配置完成。VSCode 更多配置知識能夠參考官方文檔。
VSCode 配置成功後,只須要在 VSCode 編輯器側邊欄單擊設置斷點,而後點擊「開始調試」按鈕,便可開始調試。
如下是一個 nodejs8 函數本地單步調試的流程例子:
調試 java 函數的過程和 nodejs、python 是相似的。但因爲 java 程序員一般喜歡用 IDEA、Eclipse 這樣的 IDE,因此咱們單獨拿出來講一下。
使用 VSCode 調試 java 時,須要安裝兩個插件:Language Support for Java(TM) by Red Hat
、Debugger for Java
。利用 VSCode 的插件市場安裝插件很簡單,能夠 參考。
如下是一個使用 VSCode 調試 java 類型函數的例子:
IDEA 配置
IDEA 配置 remote debugging 仍是比較簡單的,首先在菜單欄依次點擊 Run -> Edit Configurations...
:
而後新建一個 Remote Debugging:
而後咱們隨意輸出一個名字,並配置端口號爲 3000.
如下是一個配置 IDEA remote debugging 的完整流程演示:
首先將 java 函數以 debug 的方式運行起來:
fun local invoke -d 3000 java8
能夠看到函數卡在這裏了,接着咱們使用 IDEA 鏈接並開始調試。能夠經過菜單欄上的 Run -> Debug...
或者工具欄直接點擊 Debug 按鈕,便可開始調試。
如下是一個用 IDEA 進行 remote debugging 的完整流程演示:
php 的調試與其餘類型的函數調試在流程上有一些不一樣。
首先,php 的運行經過 fun local invoke php72
命令完成,這與其餘類型的函數一致。調試時,也像其餘類型的函數同樣,經過 -d 參數以調試模式啓動函數:
fun local invoke -d 3000 --config VSCode php72
但不一樣的是,以 debug 方式運行 php 函數後,php 函數並無阻塞等待 vscode 調試器的鏈接,而是直接運行結束。
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
這是由於,對於 php 程序,須要首先啓動 vscode 的調試器。
php 類型的函數啓動 VSCode 調試器的流程與其餘類型的函數一致:複製上面日誌中的 vscode 配置到 launch.json,單擊「開始調試」便可。
而後在終端從新以調試模式啓動 php 函數便可開始調試:
fun local invoke -d 3000 php72
函數計算提供了豐富的觸發器,包括但不侷限於對象存儲觸發器、日誌服務觸發器、CDN 事件觸發器等。在本地不管是運行仍是調試函數時,爲了可以徹底模擬線上環境,一般須要構造觸發事件。
觸發事件能夠是一段可讀的 json 配置,也能夠是一段非可讀的二進制數據。這裏咱們拿 json 舉例,假設觸發事件內容爲:
{ "testKey": "testValue" }
想要將這段事件內容傳給函數,能夠經過如下三種途徑:
echo '{"testKey": "testValue"}' | fun local invoke nodejs8
fun local invoke -e event.json nodejs8
fun local invoke nodejs8 < event.json
或者 fun local invoke nodejs8 <<< '{"testKey": "testValue"}'
等等。更多信息能夠參考這篇文章。在 template.yml 中配置的 EnvironmentVariables 會與線上行爲一致,當函數運行時,能夠經過代碼獲取到。更多信息參考。
在本地運行函數時,除了 EnvironmentVariables 配置的環境變量,fun 還會額外提供一個 local=true
的環境變量,用來標識這是一個本地運行的函數。
經過這個環境變量,用戶能夠區分是本地運行仍是線上運行,以便於進行一些特定的邏輯處理。
在 template.yml 中配置的 Initializer 屬性會與線上行爲一致,當函數運行時,會首先運行 Initializer 指定的方法。Initializer 更多信息 參考。
用戶能夠經過 Credentials 中存儲的 ak 信息訪問阿里雲的其餘服務。Fun local 在本地運行函數時,會按照與 fun deploy 相同的 策略 尋找 ak 信息。
關於函數計算 Credentials 的描述,能夠參考。
如下是一個根據本地、線上環境的不一樣,利用函數提供的 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 上。項目目錄結構以下:
. ├── 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 定義了函數計算模型,其中定義了一個名爲 localdemo 的服務,並在該服務下,定義了 6 個函數,名稱分別是 nodejs六、nodejs八、php7二、python2七、python三、java8。它們對應的代碼目錄由 template 中的 CodeUri 定義,分別位於 nodejs六、nodejs八、php7.二、python2.七、python三、java8 目錄。