领先一步
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 版本的成本几乎降低了 4 倍。“自定义”函数甚至更快(比 Spring Cloud Function 1.0 快 10 倍)——它是一个使用具有函数式 Bean 的 Spring Cloud Function 的自定义 AWS 运行时。改进的根本原因在于启动时间的大幅缩短,而这反过来又源于在应用程序中使用函数式 Bean 定义形式。如果您需要入门介绍,Josh 之前制作了一个关于函数式 Bean 注册的视频(在 YouTube 上)。现在让我们更仔细地看看它在 Spring Cloud Function 中是如何工作的。
这是一个来自 1.0 版的 Spring Cloud Function 应用程序,使用了熟悉的@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);
}
}
您可以通过将其与所有依赖项一起打包并上传到 Amazon 来在 AWS Lambda(例如)中运行它。该项目还支持Azure Functions 和Apache OpenWhisk。其他无服务器提供商,例如Oracle Fn 和Riff,维护自己的绑定。
您也可以仅通过在类路径上包含spring-cloud-function-starter-web
来在它自己的 HTTP 服务器中运行上面的应用程序。运行 main 方法将公开一个可用于 ping 该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 启动器,因为嵌入式 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 Cloud Function 应用程序的范围相对较小,与整个 Spring Boot 相比,因此我们可以轻松地将其适应这些函数式 Bean 定义。如果您超出该有限范围,可以通过切换回@Bean
风格配置或使用混合方法来扩展您的 Spring Cloud Function 应用程序。将相同类型的功能扩展到其余 Spring Boot 生态系统需要更长的时间,但这是我们正在积极努力的事情。如果您有时间,请尝试一下 Spring Cloud Function 2.0 并向我们提供一些反馈——GA 版本即将发布。