1.5 Spring 5与响应式编程
无论是电商类系统,还是互联网场景下的智能终端平台,都面临着大流量、高并发的访问请求。在各种请求压力下,系统就可能出现一系列可用性问题,作为系统的设计者,需要保证系统拥有即时的响应性。如何时刻确保系统具有应对请求压力的弹性,成为一个非常现实且棘手的问题。响应式编程技术针对这类问题提供了一种新的解决方案。
1.5.1 响应式编程技术
经典的服务隔离、限流、降级以及熔断等机制能够在一定程度上实现系统的弹性。通过对比更多可选的技术体系之后,可发现构建系统弹性的一种崭新的解决方案,这就是响应式编程。响应式编程打破了传统的同步阻塞式编程模型,基于响应式数据流和背压机制实现了异步非阻塞式的网络通信、数据访问和事件驱动架构,能够缓解服务器资源的竞争,从而提高服务的响应能力。
比方说,当系统中的服务A需要访问服务B时,在服务A发出请求之后,执行线程会等待服务B的返回,这段时间该线程就是阻塞的,因此整个过程的CPU利用效率低下,很多时间线程被浪费在了I/O阻塞上。更进一步,当执行数据访问时,数据库的执行操作也面临着同样的阻塞式问题。这样,整个请求链路的各个环节都会导致资源的浪费,从而降低系统的弹性。而通过引入响应式编程技术,就可以很好地解决这种类型的问题。
事实上,很多开发框架中已经应用了响应式编程技术。在1.4节中提到的Spring Cloud中存在的Netflix Hystrix组件,就是专门用来实现服务限流的熔断器组件。在这个组件中,实现了一个HealthCountsStream类来提供滑动窗口机制,从而完成对运行时请求数据的动态收集和处理。Hystrix在实现这一机制时大量采用了数据流处理方面的技术以及RxJava响应式编程框架。
再比方说,针对Spring Cloud,Spring家族还专门开发了一个网关工具Spring Cloud Gateway。相比Netflix中提供的基于同步阻塞式模型的Zuul网关,Spring Cloud Gateway的性能得到了显著的提升,因为它采用了异步非阻塞式的实现机制,而这一机制正是借助于响应式编程框架Project Reactor以及Spring 5中所内嵌的相关开发技术实现的。
1.5.2 响应式Spring中的技术组件
你可能会问,如何应用响应式编程技术呢?它的开发过程是不是很有难度呢?这点不用担心,因为随着Spring 5的正式发布,我们迎来了响应式编程的全新发展时期。Spring 5中内嵌了与数据管理相关的响应式数据访问、与系统集成相关的响应式消息通信以及与Web服务相关的响应式Web框架等多种响应式组件,从而极大简化了响应式应用程序的开发过程和降低了相应的开发难度。图1-11展示了响应式编程技术栈与传统的Servlet技术栈之间的对比。
图1-11 响应式编程技术栈与传统的Servlet技术栈之间的对比(来自Spring官网)
可以看到,图1-11左侧为基于Spring WebFlux的技术栈,右侧为基于Spring MVC的技术栈。我们知道传统的Spring MVC构建在Java EE的Servlet标准之上,该标准本身就是阻塞式和同步的。而Spring WebFlux基于响应式流,因此可以用来构建异步非阻塞的服务。
在Spring 5中,选取了Project Reactor作为响应式流的实现库。由于响应式编程的特性,Spring WebFlux和Reactor的运行需要依赖于诸如Netty和Undertow等支持异步机制的容器。也可以选择使用较新版本的Tomcat和Jetty作为运行环境,因为它们支持异步I/O的Servlet 3.1。图1-12更加明显地展示了Spring MVC和Spring WebFlux的区别和联系。
在基于Spring Boot以及Spring Cloud的应用程序中,Spring WebFlux和Spring MVC可以混合进行使用。
另一方面,针对数据访问,从Spring Boot 2开始,对于那些支持响应式访问的数据库,Spring Data也提供了响应式版本的Repository支持。我们可以使用MongoDB和Redis等NoSQL数据库来实现响应式数据访问。
图1-12 Spring MVC和Spring WebFlux的区别和联系