$walker
微服务 · 架构 · Java · Lagom · Spring

微服务框架选型

对比 Lagom 与 Spring Cloud 技术栈,分析 Play/Lagom 和 Spring WebFlux/Spring MVC 的选型思路。

发表于 2020-01-17约 8 分钟微服务架构JavaLagomSpring

需求背景

随着业务发展,单体应用的缺点越来越明显:逻辑复杂、模块耦合、代码臃肿,改动难度大,版本迭代效率低下;一个进程承载全部业务逻辑,启动与重启耗时过长;错误隔离性差、可用性低,任何一个模块出错都可能拖垮整个系统;可伸缩性差,扩容只能整体扩容,无法对单个功能点单独扩;线上问题修复周期长,任何一次修复都要对整套应用做全面升级。

将业务适度拆分、独立微服务化,已经迫在眉睫。

主要需求

  1. 选择适合当前项目的微服务框架
  2. 改动最小化

现有技术组件

Akka HTTP 是基于 Akka Streams 的 Reactive Streams 兼容工具包,提供了完全异步、无阻塞的服务端与客户端的 HTTP 栈。它的编程模型同时提供高级路由 DSL 与底层 API。虽然在底层使用了 Akka Actors 与 Actor 模型,但 API 对最终用户隐藏了这一点。

Akka HTTP 是一组库,而非 Play、Lagom 那样的框架——与浏览器的交互也在其能力范围内,但那并非它的主要重心。Akka HTTP 的定位是集成层(而非应用核心)的灵活性。它内置了对 Akka Streams 与 Reactive Streams 流式 API 的支持,客户端 API 同样提供异步、非阻塞与流式能力。

Akka 是基于 Actor、消息驱动的运行时,用于在 JVM 上管理并发、韧性与弹性,并对 Java 与 Scala 提供一等公民级别的支持。Akka 背后的编程模型基于 Actor 模型,而 Akka Streams 则基于 Reactive Streams,提供针对流数据优化过的模型。

Akka 使用 Actor 模型简化并行处理、提升资源利用率,并提供集群能力,包括分片、无冲突复制数据类型(CRDTs)、gRPC、路由器等。它还包含 Akka Streams,用于支持带背压(backpressure)的流数据,以及 Alpakka——提供对接各类外部技术的 Akka Streams 端点。

Reactive 简介

2014 年,Lightbend 联合创始人兼 CTO Jonas Bonér 与社区共同定义并阐述了 Reactive(响应式),即“响应式宣言(Reactive Manifesto)”,如今已有全球超过 24,000 人签名。该宣言已被业界广泛采纳,并有效提出了真正的云原生应用设计原则。

响应式系统具备以下特质:

支撑“在高韧性之上兼具弹性”的基础设施原则是——系统应当:

Web 框架

微服务框架

Lagom(Reactive)

Lagom 在瑞典语中意为“恰到好处”。微服务常被理解成“小型服务”,但 Lightbend 想强调的是:在构建基于微服务的系统时,最重要的不是服务的大小,而是找到服务之间正确的边界,使其与限界上下文(Bounded Context)、业务功能与隔离需求保持一致。因此,它非常适合以领域驱动设计(DDD)为重点的思维方式。

遵循这一思路,有助于构建易于部署与管理的、可伸缩且有韧性的系统。Lightbend 的观点是:重点不应放在服务的大小上,而应是“大小合适”的服务,也就是 Lagom 尺寸的服务。Lagom 基于“响应式宣言”定义的响应式原则,为开发者提供了良好的默认值(safe by default),并在必要时允许偏离。

Lagom 框架充当多个 Lightbend 框架的抽象层,由以下核心技术与框架组成:

核心概念

Lagom 发展历程

Lagom 1.0 版本

Lagom 依赖 sbt 的某些特性,因此支持其他构建工具并不容易。虽然支持 Maven 或许可行,但仍需构建概念验证(PoC)来验证。

据 Lightbend 的说法,Scala 的构建工具 sbt 为 Lagom 带来了许多便利:快速增量重编译、热代码重载、并行启停服务、自动注入配置默认值等。但在多数 Java 开发者眼中,sbt 是一道门槛——统治 Java 项目的主要是 Maven 与 Gradle(在较小程度上还有 Ant)。向 Lagom 这类微服务框架迁移本身已是相当大的转变,因此我们认为这可能会劝退 Java 开发者。把品牌从“偏 Scala 的公司”重塑为“更具 Java 意识的厂商”,正契合降低初期学习曲线的诉求,尤其对构建工具这类“细枝末节”而言。毕竟,提升采用率最重要的事,是让人们能轻松上手新技术。我们认为为 Maven 或 Gradle 提供集成会对采用率产生积极影响——尽管实现不易,但有助于说服 Java 开发者放下顾虑使用 Lagom。

Lagom 1.1 版本

2016 年 9 月,Lightbend 发布了 Lagom 1.1,引入了 Maven 支持,包括在 Maven 中运行 Lagom 开发环境的能力。

Lagom 1.2 版本
Lagom 1.3 版本
Lagom 1.4 版本
Lagom 1.5 版本

Spring Cloud(生态成熟,资料丰富)

选型组合

  1. Play + Lagom(Lightbend 技术栈)
  2. Spring WebFlux + Spring Cloud(Spring 技术栈)
  3. Spring MVC + Spring Cloud(Spring 技术栈)

vs Spring

Lagom

在我看来,Lagom 的开发环境极大地提升了生产力——一条命令启动所有微服务,代码热重载,以及富有表现力的服务接口声明,都是 Lagom 高度重视开发者生产力的体现。

建立良好的构建实践,正是 Lagom 响应式服务所看重的,例如默认异步通信、ES/CQRS 等。

Spring

Spring 已存在十余年,随着 Spring Boot 与 Spring Cloud 的出现,趋势逐渐转向以独立应用作为微服务开发的基础。Spring 吸收了 Netflix OSS 的成果,同时提供了自己的组件,如 Spring Cloud Config 与 Spring Security。Netflix 与 Spring 技术栈提供了在生产环境构建与运行微服务所需的全部工具。

外部化配置、开箱即用的服务注册仪表盘、断路器监控与分布式追踪、与 Eureka/Consul/Zookeeper 等服务注册表的集成、面向 Actuator 端点的生产级监控与指标能力、与 Maven/Gradle 等构建工具的集成,以及广泛的安全特性(包括即将与 Vault 的集成)——这些只是 Spring 所提供能力的一部分。

鉴于 Lagom 仍处在发展期,将其与 Spring 栈做深入对比并不公平。我们希望 Lagom 能持续迈向更成熟的框架,并在各个层面真正具备替代 Spring 的实力。目前看到的第一步令人鼓舞,也希望他们能采纳我们对框架进一步发展的建议。很高兴看到更多微服务框架涌现,我们为 Lightbend 与 Spring 同台竞争点赞。

Spring WebFlux vs Spring MVC

传统的 Spring MVC 基于 Servlet,是阻塞式的,每次请求由一个线程处理。

Spring WebFlux 不依赖 Servlet API,可运行在 Netty 等网络服务器之上。它通过事件循环(Event Loop)模式,由单个线程以非阻塞方式处理事件;当遇到耗时任务时,Event Loop 绑定的线程会新起线程执行,完成后通知 Event Loop。

相比 Servlet 的多线程处理方式,Spring WebFlux 在应对高并发请求时,借助异步 IO,能以少量且稳定的线程处理更高吞吐量的请求——尤其当请求处理因业务复杂或 IO 阻塞而耗时较长时,对比更加明显。

结论

我们认为 Lagom 前景可观,一定会持续跟进。由于 Lagom 是一个 opinionated(强约定)框架,一切都能很好地融合在一起。Lagom 只是 Akka 与 Play 之上的一层薄封装,历经多年已相当成熟稳健。

尽管仍有一些重要事项待解决,但我们相信可以得出结论:Lightbend 在认真倾听社区反馈,他们通过新功能持续改进 Lagom,并为开发者提供更好的体验。

我们的建议是:密切关注 Lagom 的进展。

如果你当前就需要一个几乎集成了所有功能的成熟框架,请选择 Spring。

如果你的项目是传统 Web 项目,例如需要集成现有 Servlet 包做过滤拦截,推荐使用 Spring MVC + Spring Cloud;否则推荐 Spring WebFlux + Spring Cloud——响应式框架在性能与速度上更具优势。

参考资料