領先一步
VMware 提供培訓和認證,助你快速提升。
瞭解更多Spring Cloud Function 在 2.0 版本(仍處於里程碑階段)中有一些新特性,其中最顯著的可能是實現“完全函式式”的能力。這得益於 Spring Boot 2.1 和 Spring Framework 5.1 的變化,它意味著 Spring 應用中 Bean 定義的一種不同思考方式,同時也顯著提升了啟動效能。
最好用一張圖來開頭,特別是它能講述一個故事時。這裡有一張圖,展示了 Spring Cloud Function 2.0 相較於 1.0 的改進,比較了 AWS 冷啟動的成本。
x 軸是記憶體大小(MB),y 軸是冷啟動成本(GBsec)。最顯著的效果體現在低記憶體容器上,2.0 版本的成本幾乎是 1.0 版本的四分之一。“Custom”函式更快(比 Spring Cloud Function 1.0 快 10 倍)——它是一個使用 Spring Cloud Function 和函式式 Bean 的自定義 AWS 執行時。改進的根本原因在於啟動時間的顯著縮短,這又來源於在應用程式中使用了函式式的 Bean 定義形式。如果你需要入門介紹,Josh 很久以前做了一個關於函式式 Bean 註冊的影片(在 YouTube 上)。現在讓我們仔細看看它在 Spring Cloud Function 中是如何工作的。
以下是 Spring Cloud Function 1.0 版本的一個應用程式示例,使用了熟悉的 `@Configuration` 和 `@Bean` 宣告風格
@SpringBootApplication
public class DemoApplication {
@Bean
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
你可以透過將其與所有依賴項一起打包成 jar 檔案並上傳到 Amazon 來在 AWS Lambda(例如)中執行它。該專案還支援 Azure Functions 和 Apache OpenWhisk。其他無伺服器提供商,例如 Oracle Fn 和 Riff,維護著自己的繫結。
你還可以透過在 classpath 中包含 `spring-cloud-function-starter-web` 來在應用程式自身的 HTTP 伺服器中執行上面的應用。執行 main 方法將暴露一個端點,你可以使用該端點來呼叫那個 `uppercase` 函式。
$ curl localhost:8080 -d foo
FOO
1.0 版本中的 Web 介面卡是使用 Spring MVC 實現的,因此你需要一個 Servlet 容器。在 Spring Cloud Function 2.0 中,你也可以使用 Webflux,並且預設伺服器是 Netty(儘管如果你願意,仍然可以使用 Servlet 容器)——只需包含 `spring-cloud-starter-function-webflux` 依賴項即可。功能是相同的,並且使用者應用程式程式碼可以在兩者中通用。
然而,在 2.0 版本中,使用者應用程式程式碼可以重寫為“函式式”形式,如下所示
@SpringBootConfiguration
public class DemoApplication
implements ApplicationContextInitializer<GenericApplicationContext> {
public static void main(String[] args) {
FunctionalSpringApplication.run(DemoApplication.class, args);
}
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}
@Override
public void initialize(GenericApplicationContext context) {
context.registerBean("demo", FunctionRegistration.class,
() -> new FunctionRegistration<>(uppercase())
.type(FunctionType.from(String.class).to(String.class)));
}
}
主要區別在於
主類是一個 `ApplicationContextInitializer`。
`@Bean` 方法已轉換為呼叫 `context.registerBean()`
`@SpringBootApplication` 已被 `@SpringBootConfiguration` 替換,表示我們沒有啟用 Spring Boot 自動配置,但仍將該類標記為“入口點”。
Spring Boot 中的 `SpringApplication` 已被 Spring Cloud Function 的 `FunctionalSpringApplication`(它是其子類)替換。
你在 Spring Cloud Function 應用程式中註冊的業務邏輯 Bean 型別是 `FunctionRegistration`。這是一個包裝類,其中包含函式以及輸入和輸出型別的資訊。在應用程式的 `@Bean` 形式中,這些資訊可以透過反射獲取,但在函式式 Bean 註冊中,除非我們使用 `FunctionRegistration`,否則部分資訊會丟失。
使用 `ApplicationContextInitializer` 和 `FunctionRegistration` 的另一種方法是讓應用程式本身實現 `Function`(或 `Consumer` 或 `Supplier`)。例如(與上述等效)
@SpringBootConfiguration
public class DemoApplication implements Function<String, String> {
public static void main(String[] args) {
FunctionalSpringApplication.run(DemoApplication.class, args);
}
@Override
public String apply(String value) {
return value.toUpperCase();
}
}
新增一個獨立的、型別為 `Function` 的類,並使用 `run()` 方法的另一種形式將其註冊到 `SpringApplication` 中也是可行的。關鍵在於透過類宣告在執行時獲得泛型型別資訊。
如果你新增 `spring-cloud-starter-function-webflux` 依賴,應用程式就可以在其自身的 HTTP 伺服器中執行(目前與 MVC starter 不相容,因為嵌入式 Servlet 容器的函式式形式尚未實現)。該應用程式在 AWS Lambda 或 Azure Functions 中也能正常執行,並且啟動時間有了顯著改進(如上圖所示)。下圖展示了另一張圖中的啟動時間(y 軸為啟動時間,單位為秒)。
Spring Cloud Function 2.0 還提供了一些用於整合測試的實用工具,這些工具對於 Spring Boot 使用者來說會非常熟悉。例如,這是一個用於測試上述應用程式 HTTP 伺服器包裝的整合測試示例。
@RunWith(SpringRunner.class)
@FunctionalSpringBootTest
@AutoConfigureWebTestClient
public class FunctionalTests {
@Autowired
private WebTestClient client;
@Test
public void words() throws Exception {
client.post().uri("/").body(Mono.just("foo"), String.class)
.exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("FOO");
}
}
這個測試幾乎與你為同一個應用程式的 `@Bean` 版本編寫的測試完全相同——唯一的區別是使用了 `@FunctionalSpringBootTest` 註解,而不是常規的 `@SpringBootTest`。所有其他部分,比如 `@Autowired` 的 `WebTestClient`,都是標準的 Spring Boot 特性。
Spring Boot 與函式式 Bean 註冊配合得很好——Spring Cloud Function 構建並執行在 Spring Boot 上——但 Spring Boot 中一些最有用的特性,即自動配置,都是以非函式式風格編寫的。與整個 Spring Boot 相比,大多數 Spring Cloud Function 應用的範圍相對較小,因此我們可以輕鬆地將其適應這些函式式 Bean 定義。如果你超出了這個有限的範圍,可以透過切換回 `@Bean` 風格的配置或採用混合方法來擴充套件你的 Spring Cloud Function 應用。將類似的功能擴充套件到 Spring Boot 生態系統的其餘部分還需要一些時間,但我們正在積極地開展這項工作。請嘗試使用 Spring Cloud Function 2.0,如果有時間,請向我們提供一些反饋——GA 版本即將釋出。