朱晔和你聊Spring系列S1E1:聊聊Spring家族的几大件
朱晔和你聊Spring系列S1E1:聊聊Spring家族的几大件
Spring家族很庞大,从最早先出现的服务于企业级程序开发的Core、安全方面的Security、到后来的作为各种数据源桥梁的Data、最近几年很火的Boot,以及最新推出的正在蓬勃发展的Cloud(在本文之后都简单称为Boot、Cloud省略Spring节省一点我的打字时间😊)。
上面这个脑图给出了Spring家族主要的一些成员,右侧非Cloud部分列的是功能,左侧Cloud部分虽然组件繁杂,但是结构清晰(确实新版本清晰多了,命名也统一,你可以放大图片看一下这些是否熟悉),所以更进一步列出了组件要的一些模块依赖和开启功能的主注解。
我说Spring的发展
Spring框架几乎涉及到了Java企业级服务开发的所有方面,也几乎针对所有开发常用的模式、中间件、数据库进行了整合适配。
之前在聊互联网架构模式的时候我谈到过,很多时候我们写一个业务把逻辑写死写出来是比较容易的,但是把这个逻辑提取成模式进而打包成一个框架来给大家使用,这是比较难的。因为我们只有经历过足够多的场景后才能提取出普适的功能框架,大部分人才能用上,而且我们需要针对核心功能开放出可配置的部分,满足小部分人进一步定制和扩展功能的需要。
Spring框架经历了几个阶段:
- 第一个阶段推出的Core、Security、Data是把单体应用开发服务好。不仅仅提供了便捷的数据库访问、Web MVC等必要功能,而且通过AOP、IOC两大利器让我们的程序内在能够做到低耦合可扩展。
- 第二个阶段推出的Boot的意义不仅仅是加速了开发效率而且能让我们的程序从可用变为好用,应用程序核心业务逻辑可能只有70%的工作量,要让程序在线上跑的愉快还有30%的监控日志打点等工作量需要去做。
- 第三个阶段推出的Cloud的意义在于推动了微服务架构的落地。让不具备开发微服务基础套件的小型互联网公司也能享受到免费的开箱即用的微服务解决方案。其实很多人不是看了微服务的架构思想去寻找解决方案,而是了解到了Spring Cloud才去了解微服务思想从而落地的。
- 目前属于第四个阶段,大力发展Cloud Dataflow+容器。Dataflow的思想是不管是做实时消息处理的服务还是临时运行的任务,都可以认为是服务的组件,如果可以有一套DSL来定义这些组件之间的交互方式,然后在容器中进行自由组合、部署、伸缩,那么架构会非常灵活。下图是Dataflow管理界面的一个示意图。
Spring的发展可以看到互联网架构的发展,Spring给我们带来相当多的技术启发,从软件设计模式的启发慢慢到了架构的启发,甚至我觉得Spring是为Java开发打造了架构风格的模板,接下去Spring继续发展2到3年有望成为架构标准,我在想这个时候应用架构师何去何从?
我说Spring Core
Spring Core提供的IOC、AOP功能已经变为半个Java命根子了。其实很多开发平台并不是那么强调IOC和AOP,甚至有的平台完全没有相关支持。虽然我一直觉得IOC和AOP是非常好的思想,可以让我们的软件内部做到组件之间的低耦合,容易替换,容易扩展,但是我的观点是,作为一个类库不应该把自己组件的初始化以及组装工作交给外部来做。我们知道通过IOC容器来管理我们组件的实例化和依赖,其实我们可以在程序内部实现每一个组件,把装配工作交给XML配置进行,但是对于一些复杂的组件,如果这个工作的配置交给XML进行,那么也就相当于交给了使用者进行,相当于需要使用者一定要理解组件内部的装配结构,这是不合理的。更合理的方式是,组件或框架的作者提供一些扩展点,让使用者可以明确通过API来注入自己的扩展组件或实现组件,而对于只需要简单使用组件的使用者可以无需配置开箱即用。
当然,这不是说Spring的IOC和AOP有什么不好,正因为框架实现的如此灵活,Java使用Spring作为容器也基本是标准了,所以Java界很多框架也因此可以相互进行很好的集成,确实是一个很好的平台。
Spring 5推出了Reactive非阻塞技术栈,基于Netty或Servlet 3.1+容器,提供了Stream API、WebFlux以及各种响应式的存储(各种NOSQL)访问类库。从前到后实现非阻塞的服务,可以避免IO阻塞占据线程,减少线程切换和资源使用,以最小的资源做到最大化的并发。可惜的是JDBC目前并没有非阻塞的版本,这样我们主流的基于MySQL的应用并不能进行全链路(从Controller到外部的Rest服务到数据库)的非阻塞IO(一竿子到底这样才是最爽的)。而且对于Reactive套件,我经过简单的使用个人感觉API比较晦涩,链式调用可读性并不高,而且反而遇到了并发的一些坑,加上代码的示例和最佳实践现在也很少,我感到现在使用并不是特别成熟。
我说Spring Data
Spring Data希望以相对比较一致的Template API来让我们更方便得使用各种数据存储。我个人不太喜欢习惯使用Data套件而是更喜欢使用各种NOSQL的Java原生客户端。几个原因:
- 原生客户端紧跟服务端的实现,可以第一时间体验到最新的功能
- 原生客户端的API和服务端提供的API往往一一匹配,可以一竿子到底,让我们功能使用更准确
- 原生客户端往往只是基于API的简单封装,性能更好
当然,如果我们只是对NOSQL进行简单使用的话,Spring Data可能使用起来更方便。
我说Spring Boot
稍微老一点的Java开发基本都是从纯XML配置到XML+注解配置走过来的,比较有意思的是很多开发虽然当初在使用XML配置,但是往往问他们每一个配置的含义都不能准确回答出,基本就是拿着主管或前人搭建的一套XML配置直接复制粘贴过来使用。从侧面说明了,其实我们大部分那些Mybatis、Spring MVC的配置都是在干组件初始化而不是定制化的事情。从0开始要让一个组件用起来就需要这些基本的配置,既然是这样的话,其实完全可以有默认配置,采用约定大于配置的方式来做。只有在我们需要针对组件进行定制化的时候才去做更多配置。
Spring Boot不但在自动配置、配置简化上做了很多工作,而且还提供了轻量的嵌入式的容器,只需要20行的Pom+10行代码,就可以立即实现一个可以自启的应用程序(部署简单)激发了我们使用微服务的热情。此外也给我们做了很多Production-ready的启示(Actuator),告诉我们一个完善的应用程序应当注重环境切换、监控、日志、打点等等方面。总之,之前我们可能需要半天时间搭建一个项目,现在通过start.spring.io甚至只需要10秒。在有Boot之前,我实在没有兴趣使用重量级的Java(可能就为了访问下数据库做一些处理,还是使用Python算了)来创建一个实验性的控制台应用程序。
我说Spring Cloud
上图来自官网首页,很好地阐述了各个组件之间的关系。我们来逐一过一下脑图上的那些组件:
- 配置管理Cloud Config:提供了客户端和服务端,客户端的使用方式和Spring完美结合,服务端提供了Git方式和文件方式的数据存储,最新版本也提供了数据库方式。这个配置管理的功能上和之前《朱晔的互联网架构实践心得S1E5:不断耕耘的基础中间件》一文中我探到的那些配置管理的功能差十万八千里。
- 服务发现Netflix Euerka:提供可客户端和服务端(兼管理台),这里的客户端是指服务发现的使用方,其实微服务中的服务在这里是客户端。
- 断路器Netflix Hustrix:提供了客户端API、聚合服务端Tubine和Dashboard网站。
- 服务网关:有Netflix Zuul和Cloud Gateway两种网关可以选择,后者据说性能更好。网关其实就是典型的Filter+Handler的实现机制,通过路由找到合适的Handler,然后调用Pre和Post的各种插件式Filter。
- 调用链跟踪Cloud Sleuth:可以搭配Zipkin使用,功能只能说凑活用。Zipkin的那后台功能上和国内主流互联网实现的Trace后台功能相比还是太弱了。
- 消息驱动Cloud Stream:抽象成为了产出消息的Source,消费数据的Sink和抓换数据的Processor。然后把Broker的实现通过Binder进行解耦,支持主流的Kafka、KafkaStream和RabbitMQ三种类型。
- 消息总线Cloud Bus:抽象了MQ的功能,支持主流的MQ产品。
- 函数即服务Cloud Function:把函数封装为Web服务或Stream服务可以独立调用。对函数编程的Function、Consumer和Supplier分别映射成为了Processor、Sink和Source。
- 微服务契约Cloud Contract:实现契约优先的编程,可以先定义契约对契约进行测试,同时进行服务实现。复杂的服务可以用这套方式来做,消费者提供者对着契约自己编自己的,两不耽误。
- 任务框架Cloud Task:非定时任务的概念,这里的任务是指一次性运行的进程。框架提供了任务执行审计管理最基本的功能。这里的任务最后可以在Cloud Dataflow中运行也可以独立运行。
- 管理台:这里列的Admin管理台是第三方提供的,基于Actuator的端点进行信息的综合展示和监控。
总结一下,总体上我感觉Cloud模块化的思想很好,模块和模块之间可以相互搭配使用,但是可能一开始没有进行系统性的规划,版本的升级带来的Breaking Changes有点过多,而且因为内容太多了,文档方面没有特别全面,要全部用起来坑会比较多,需要享受新功能的话还需要不断更新框架版本不断踩坑。
从目前功能的完善程度来说我感觉核心功能完善度在60%(大概还需要发展1年可以用的比较舒服)。后台方面过于简陋,官方提供的后台零散丑陋而且完成度极低(相比国内一线互联网在治理这块开发的功能来说,完善度大概在30%,大概还需要发展2年可以用的比较舒服,如果可以好好规划一套完整的后台把服务治理所有相关功能都整合在一起就好了)。不管怎么样,至少Cloud套件是一套完整的解决方案,目前来看还没有可以媲美的其它开源选择可以使用(Dubbo我们也知道虽然现在又开始高速迭代,但是由于其原始定位是RPC框架,理念上还是有很多不同的,组件方面并没有Cloud那么完善)。
除了功能不完善,Cloud令我担心的还有一点是(我没测试过,但是因为看到目前功能的迭代速度对这方面信心不足,谁大规模应用了能否可以给点数据),这些中间件(服务发现、网关服务、链路跟踪、配置管理)是不是经过压测,是否可以满足比较大的压力,如果只是实现功能的话,可能会在全面用起来后遇到性能瓶颈,在这个时候恐怕就麻烦了。
总结
Spring家族已经是功能强大的庞然大物了,我们的项目pom中出现几十个Spring依赖也是家常便饭。使用.NET家族的套件也是几年前的事情了,但是至今我还是觉得微软.NET的开发套件不管是MVC还是ORM还是RPC方面比Spring的MVC、Data JPA(现在大家都使用Mybatis,Mybatis也还是太弱了)、Cloud套件在功能和设计的优雅上更胜一筹,希望将来可以看到Spring针对这些点继续发力,并且持续打造Dataflow套件,结合K8S打造成一个微服务的OS(各种中间件可以实现一键部署集群)。另外对于Spring Cloud除了核心功能之外,希望在管理台方面可以继续完善,打造一个一体化(不一定是一个网站,但是至少可以有权限控制和审计,实现SSO)的管理台,全面实现微服务部署伸缩、服务治理、数据流程管理、服务全链路监控、配置管理等等功能,也期待Spring Cloud和Dataflow双剑合璧在将来的2到3年定义微服务和以数据为核心的流处理的架构标准。