1 SpringBoot 的设计初衷
1.1 应用迭代快
为了适应市场变化的需求,应用的更新迭代速度越来越快,所以如果还是基于SpringMVC 和 Tomcat 这套应用开发和部署方案,则会由于需要进行大量配置而影响开发效率,拖慢项目的开发进度。
1.2 Spring 应用配置方式固定
Spring 应用一般包括应用自身的配置和对第三方功能 jar 包依赖的配置,而这些配置的模式一般是固定的。
首先是基于 Spring 实现的 Web 应用肯定需要配置对 SpringMVC 框架和 Java Servlet 相关功能 jar 包的依赖,并且需要在应用配置文件 web.xml 中配置 DispatcherServlet 与其 URI 映射等。
其次是对于项目中依赖的功能 jar 包的版本冲突问题,其实也是可以统一测试和解决好,避免每个开发者都重复折腾一次。具体为可以将实现某个大功能的多个 jar 包进行测试,然后打包到一个汇总 jar 包,并为该汇总 jar 包指定一个版本。这样开发人员可以在项目中直接引入这个测试好、不存在版本冲突问题的汇总 jar 包即可,从而既加快了开发速度,又提高了程序的健壮性。
1.3 微服务架构的兴起
除了需要对项目进行快速迭代之外,当今主流的互联网应用都是并发量非常高的应用,这是跟传统的企业内部应用不一样的。
所以为了应对高并发应用场景,互联网应用一般都是采用分布式和微服务架构,将一个单体应用的多个功能模块拆分为多个独立部署运行的子服务,并且每个子服务可以通过集群部署来提高吞吐量,避免单点故障问题等。
如下是电商网站的微服务架构和集群部署示意图:
知识拓展:
基于分布式与微服务架构设计的应用相对于一个完整的单体应用,每个子服务的部署实例对服务器资源的要求较低,但是需要部署的子服务实例的个数则增加很多,原因是单体应用的每个功能模块都可以对应一个子服务。
在部署层面,一般需要在大量配置较低的廉价机器或者是虚拟机而不是物理机中部署这些子服务。所以如果是基于传统的 SpringMVC 和 Tomcat 部署的开发模式,需要在每个机器或者虚拟机都部署一个 Tomcat 进程。这对于存在大量服务实例的分布式系统而言,无疑会增加运维的负担,以及造成机器资源的浪费。
1.3 SpringBoot 框架的推出
针对以上这些背景,Pivot 开发团队从 2013 年开始着力设计和开发 SpringBoot 框架,并在 2014 年 4 月发布 1.0.0 版本。
SpringBoot 框架并不是像 Spring 和 SpringMVC 这种全新的、实现某个功能的应用框架,而是一种用于简化 Spring 应用开发,实现应用快速开发迭代的解决方案。SpringBoot 框架主要解决了在第 1 节提到的基于 SpringMVC 开发 Java Web 应用存在的开发效率低的问题,以及解决需要依赖 Tomcat 进程来运行 Java Web 应用的问题,最终简化了 Spring 应用的搭建、开发和维护。
如下将通过分析 SpringBoot 提供的核心功能来分析 SpringBoot 是如何解决 Java Web 开发的痛点问题的。
2 SpringBoot 的核心功能
以下基于 SpringBoot 应用的开发流程来分析 SpringBoot 的核心功能和每个功能解决了基于 SpringMVC 来 Java Web 应用开发的哪个痛点。
2.1 应用初始搭建:约定优于配置理念与 starter 包
应用初始搭建时,在基于 maven 进行包依赖管理的 Spring 应用中,首先需要在 pom.xml 文件中一个个地配置当前应用所需要的功能 jar 包和指定所需的版本,然后需要进行测试来检查是否少配了某些包或者是否存在包冲突问题,而针对某个功能,其所需的功能 jar 包通常是固定的。
所以 SpringBoot 基于 实现某个功能的 jar 包是固定的事实,提出了约定优于配置的理念,其中约定的意思是实现某个功能所需要的功能 jar 包是固定的,所以可以将实现该功能的多个相关 jar 包打包到一个更大的 jar 包中,通过这个更大的 jar 包即可引入实现该功能的所有 jar 包,这个更大的 jar 包就是 SpringBoot 的 starter 包。
知识拓展:
SpringBoot 的 starter 包除了汇总了实现某个功能的 jar 包,使得应用只需引入对应的 starter 包,而不需要一个个地引入多个功能 jar 包来简化包的配置之外,还有一个好处就是由 SpringBoot 统一管理 jar 包的版本:SpringBoot 在发布一个新版本的 starter 包时,会预先对其所包含的多个功能 jar 包进行测试和解决包的类冲突问题,使得应用开发人员只需要引入对应的 starter 包即可,而无需担心 jar 包的兼容和类冲突问题。
2.2 应用配置:自动配置
在 Spring 应用的开发当中,需要分别在 applicationContext.xml 文件对 Spring 容器进行配置,在 dispatcher-servlet.xml 文件对 SpringMVC 进行配置,其次还需要在 web.xml 对 SpringMVC 的 DispatchServlet等进行配置。
为了解决这些繁杂的应用配置问题,SpringBoot 实现了一种自动配置机制。SpringBoot 根据应用当前引入了哪些 starter 包来自动创建对应功能的 bean 对象,具体为:如果应用引入了某个功能的 starter 包并在 properties 文件配置了相关参数,但是没有主动定义相应类型的 bean 对象,如在 applicationContext.xml 文件中通过 标签定义或者在 Java 配置类通过 @Bean 注解某个方法来定义,则 SpringBoot 会自动创建该类型的 bean 对象,使得在应用中直接使用即可。
关于 SpringBoot 自动配置的相关实现原理和用法将在后续的章节中详细分析,敬请期待_。
2.3 应用部署:独立 Java 进程运行
传统的 Java Web 应用都需要打 war 包,然后部署到 Tomcat 进程中来运行,由 Tomcat 进程来接收客户端的请求和返回响应,所以在服务器中需要额外运行 Tomcat 进程来部署 Java Web 应用,这在微服务架构下存在非常多的子服务的场景中,无疑会增加运维难度和机器资源的浪费。
所以 SpringBoot 框架通过在内部嵌套 Servlet 引擎的方式来实现 SpringBoot 应用以独立的 Java 进程运行,而无需依赖于额外部署的 Tomcat 进程。
具体为在 SpringBoot 应用启动运行时,会在内部启动一个Servlet 引擎并在指定的端口监听客户端的连接请求。说白了就是 SpringBoot 框架自身就相当于一个 Servlet 容器 Tomcat,所以可以接收客户端的连接和处理客户端的请求。
tips:对于以独立 Java 进程的方式来运行 SpringBoot 应用的好处是:除了不需要在服务器额外启动 Tomcat 进程和简化运维的难度外,还实现了可以为该 Java 进程指定运行时参数,如 JVM 参数,从而可以根据每个应用自身的特点来指定对应的运行时参数,灵活地进行 JVM 调优。
2.4 应用运行监控:Actuator
Spring 应用自身是没有监控的,如果需要对 Spring 应用的运行情况进行监控,则需要结合第三方监控软件或者使用 Linux 命令来查看系统的相关负载情况。
在单体应用架构中,这种使用第三方监控的方式问题不大,因为只需要对该应用的部署实例进行监控即可。但是在微服务架构中,一个系统会存在多个子服务并且每个子服务都是独立部署的,故会出现大量的部署实例。此时如果每个子服务都依赖第三方监控则运维工作量会非常大。
为了解决微服务架构下 Spring 应用的运行时监控和管理问题,SpringBoot 开发了 Actuator 应用监控功能。SpringBoot Actuator 是以单个 SpringBoot 应用为监控粒度,监控的内容包含当前应用的健康状况,运行环境,内存用量,Http 请求计数统计,以及 Spring 应用 beans 的加载信息等。而这些信息可以通过 Restful API 请求获取。关于 Actuator 监控功能的更多细节在之后的章节中详细分析,敬请期待 ~
3 总结
在本节当中我们首先介绍了当前企业应用开发的现状和 Pivot 团队推出 SpringBoot 框架的初衷。接着我们介绍了 SpringBoot 的几大核心功能,具体包括:
SpringBoot 基于约定优于配置的理念设计了 starter 包和自动配置机制,通过 starter 包可以降低应用搭建时的功能 jar 包的配置难度;通过自动配置机制,减少了应用配置的数量,即对于应用中需要用到的功能组件对应的 bean 对象,可以直接注入使用,无需进行一系列的配置。
除此之外,通过以独立的 Java 进程来启动 SpringBoot 应用,省去了传统的 Java Web 应用对额外部署的Servlet 容器 Tomcat 的依赖,并且可以更加方便地自定义应用的运行时参数。最后介绍了 SpringBoot 的应用监控功能 Actuator,通过 Actuator 可以对每个 SpringBoot 应用的运行状况进行监控和管理。