Cloud Native Spring in Action

目录

设计原则

[15 Factor App](#15 Factor App)

数据验证和错误处理

测试

[使用 Junit 5 进行单元测试](#使用 Junit 5 进行单元测试)

[使用 @SpringBootTest 进行集成测试](#使用 @SpringBootTest 进行集成测试)

[使用 @WebMvcTest 测试 REST Controller](#使用 @WebMvcTest 测试 REST Controller)

[使用 @JsonTest 测试 JSON 序列化](#使用 @JsonTest 测试 JSON 序列化)

[使用 @DataJdbcTest 和 Testcontainers 测试数据持久化](#使用 @DataJdbcTest 和 Testcontainers 测试数据持久化)

[使用 Reactor 和 Testcontainers 测试 Reactive 应用](#使用 Reactor 和 Testcontainers 测试 Reactive 应用)

[使用 MockWebServer 测试 REST client](#使用 MockWebServer 测试 REST client)

[使用 @DataR2dbcTest 和 Testcontainer 测试数据持久化](#使用 @DataR2dbcTest 和 Testcontainer 测试数据持久化)

[使用 @WebfluxTest 测试 REST Controller](#使用 @WebfluxTest 测试 REST Controller)

Testcontainers

数据持久化与数据管理

[JDBC 审计](#JDBC 审计)

[Flyway & Liquibase](#Flyway & Liquibase)

Liquibase

安全

[Spring Security & Spring Cloud API Gateway](#Spring Security & Spring Cloud API Gateway)

OAuth2

JWT

[OpenID Connect](#OpenID Connect)

KEYCLOAK

定义安全realm

[OIDC 认证](#OIDC 认证)

CSRF

韧性

超时

重试

回退和错误处理

[基于 Redis 的分布式会话管理](#基于 Redis 的分布式会话管理)

Kubernetes

Deployment

Service

[ConfigMap & Secret](#ConfigMap & Secret)

[Ingress & Ingress Controller](#Ingress & Ingress Controller)

[Volumn & Persistence Volumn & Persistence Volumn Claim](#Volumn & Persistence Volumn & Persistence Volumn Claim)

Pod

Replicaset

配置管理

Kustomize

Helm

[Argo & Jenkins](#Argo & Jenkins)


英文版:《Cloud Native Spring in Action》,Thomas Vitale 著

中文版:《云原生 Spring 实战》Spring Boot 与 Kubernetes 实践

设计原则

15 Factor App

"15 Factor App"是在"12 Factor App"基础上发展而来,新增的三个要素分别是:

  1. API First(API 优先):强调在应用程序开发中,优先设计和定义 API。这使得应用程序的各个模块或服务之间能够通过清晰、标准的 API 进行交互通信。遵循 API First 的原则,开发团队可以更好地实现软件的解耦,提高开发效率和系统的可维护性。并且在现代云原生应用中,通过 API 可以方便地与其他微服务或外部系统进行集成,提升了应用的灵活性和可扩展性。例如,使用 API 网关来管理和规范 API 的调用,遵循最佳的 REST API 实践,定义好请求、响应 payload、API 名称、安全等方面的规范。

  2. Telemetry(遥测):包括应用性能管理、特定领域的遥测数据以及健康和系统日志等方面。对应用程序的运行状态、性能指标、资源使用情况等进行实时监测和收集,能够帮助开发团队和运维人员及时了解应用的运行状况,以便在出现问题时快速定位和解决。基于这些遥测数据,平台还可以进行自动扩缩容、自我修复以及向用户和运维人员发送警报等操作。通过机器学习等技术对遥测数据进行分析,还可以为企业的未来业务策略提供参考。

  3. Authentication and Authorization(认证和授权):在现代应用中,安全是至关重要的。这一要素确保只有经过认证的用户和应用程序能够访问系统资源,并根据不同的用户角色和权限进行授权。例如,采用 API token、RBAC(基于角色的访问控制)、OAuth 等认证和授权机制,对 API 的请求和响应 payload 进行加密,在网络层面设置防火墙保护,保障数据库的安全以及采用多因素认证(MFA)等措施。

这三个新增要素适应了现代云原生应用的发展需求,使得应用程序在云环境中能够更加高效、可靠、安全地运行。

12 Factor App

https://12factor.net/

  • Codebase 基准代码
  • Dependencies 依赖管理
  • Config 配置
  • Backing Services 支撑服务
  • Build Release and Run 构建、发布和运行
  • Processes 无状态进程
  • Port Binding 端口绑定
  • Concurrency 并发
  • Disposability 易处理
  • Dev/Prod Parity 环境对等
  • Logs 日志
  • Admin Processes 管理进程

数据验证和错误处理

spring-boot-starter-validation:@NotBlank、@NotNull、@Pattern、@Positive、@Valid 等。

测试

spring-boot-starter-tester:会将 JUnit 5、Mockito 和 AssertJ 的测试库导入项目。

使用 Junit 5 进行单元测试

使用 @SpringBootTest 进行集成测试

使用 @WebMvcTest 测试 REST Controller

使用 @JsonTest 测试 JSON 序列化

使用 @DataJdbcTest 和 Testcontainers 测试数据持久化

使用 Reactor 和 Testcontainers 测试 Reactive 应用

使用 MockWebServer 测试 REST client
使用 @DataR2dbcTest 和 Testcontainer 测试数据持久化
使用 @WebfluxTest 测试 REST Controller

Testcontainers

Testcontainers是一个Java库,用于在测试中方便地管理容器。

主要功能

• 容器生命周期管理:可以轻松启动和停止容器。例如,在测试数据库交互时,能快速启动一个数据库容器(如MySQL、PostgreSQL),测试完成后自动停止它。这样避免了手动安装和配置数据库,使测试环境搭建更便捷。

• 支持多种容器类型:除了常见的数据库容器,还支持消息队列容器(如RabbitMQ、Kafka)、Web容器(如Tomcat、Jetty)等。如果测试的应用依赖于这些服务,就可以用对应的容器来提供真实的测试环境。

• 与测试框架集成:很好地集成了JUnit等流行的Java测试框架。在JUnit测试类中,可以通过简单的注解和方法调用就启动和使用容器。

使用示例

  1. 添加依赖:在Maven项目的pom.xml文件中添加以下依赖:

<dependency>

<groupId>org.testcontainers</groupId>

<artifactId>testcontainers</artifactId>

<version>1.18.3</version>

</dependency>

<dependency>

<groupId>org.testcontainers</groupId>

<artifactId>junit - jupiter</artifactId>

<version>1.18.3</version>

</dependency>

  1. 测试数据库交互(以MySQL为例)

import org.junit.jupiter.api.Test;

import org.testcontainers.containers.MySQLContainer;

import org.testcontainers.junit.jupiter.Container;

import org.testcontainers.junit.jupiter.Testcontainers;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

import static org.junit.jupiter.api.Assertions.assertTrue;

@Testcontainers

public class DatabaseTest {

// 启动MySQL容器

@Container

public static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:8.0")

.withDatabaseName("test_database")

.withUsername("test_user")

.withPassword("test_password");

@Test

public void testDatabaseConnection() throws SQLException {

// 获取容器的JDBC URL

String jdbcUrl = mySQLContainer.getJdbcUrl();

try (Connection connection = DriverManager.getConnection(jdbcUrl, "test_user", "test_password");

Statement statement = connection.createStatement()) {

// 执行一个简单的SQL查询

statement.execute("CREATE TABLE IF NOT EXISTS test_table (id INT, name VARCHAR(255))");

int result = statement.executeUpdate("INSERT INTO test_table (id, name) VALUES (1, 'test')");

assertTrue(result > 0);

}

}

}

在这个示例中:

• 首先定义了一个MySQLContainer,它会在测试运行时自动启动一个MySQL 8.0版本的容器,并且配置了数据库名、用户名和密码。

• 在测试方法中,通过getJdbcUrl获取容器的JDBC连接地址,然后建立连接,创建表并插入数据,最后验证插入操作是否成功。

Testcontainers极大地简化了测试环境的搭建,让测试能够在接近生产环境的容器化环境中进行,提高了测试的可靠性和有效性。

数据持久化与数据管理

JDBC 审计

使用 @EnableJdbcAuditing 启用 JDBC 审计

在配置类添加 @EnableJdbcAuditing 后,@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate 这些字段都可以加载实体字段上以捕获审计信息。

Flyway & Liquibase

Flyway和Liquibase都是管理数据库的工具,主要区别如下:

工作方式

• Flyway:基于版本号的方式管理数据库迁移。它要求开发者为每个迁移脚本按顺序编号,如V1__Create_user_table.sql、V2__Add_user_name_column.sql。在执行迁移时,Flyway会按版本号从小到大依次执行这些脚本。

• Liquibase:通过XML、YAML或SQL格式的变更日志文件来管理数据库迁移。变更日志文件描述了数据库的一系列变更,它不依赖于文件名中的版本号顺序,而是在日志文件里定义操作的顺序。

对数据库的支持

• Flyway:支持常见的数据库,如MySQL、PostgreSQL、Oracle等,但对某些数据库的特定功能支持可能有限。

• Liquibase:支持更广泛的数据库类型,包括一些比较小众的数据库,而且对不同数据库的兼容性较好,在复杂数据库环境下更有优势。

学习曲线

• Flyway:比较简单直接,容易上手,适合中小规模的项目,尤其是团队成员对数据库迁移工具不太熟悉的情况。

• Liquibase:功能强大但稍复杂,学习成本相对高些,不过它的灵活性使其适用于大型企业级项目。

集成能力

• Flyway:能很好地与构建工具(如Maven和Gradle)集成,在项目构建过程中方便地执行数据库迁移任务。

• Liquibase:除了构建工具集成外,还提供了多种接口和插件,能与不同的开发框架和部署环境集成。

Liquibase

https://docs.liquibase.com/home.html

安全

Spring Security & Spring Cloud API Gateway

OAuth2

JWT

OpenID Connect

KEYCLOAK

定义安全realm

OIDC 认证

CSRF

韧性

超时

重试

回退和错误处理

基于 Redis 的分布式会话管理

Kubernetes

Deployment

Service

ConfigMap & Secret

Ingress & Ingress Controller

Volumn & Persistence Volumn & Persistence Volumn Claim

Pod

Replicaset

配置管理

Kustomize

Helm

Argo & Jenkins

Argo和Jenkins都是用于自动化软件交付流程的工具,但它们之间有一些区别。

工作流定义方式

• Jenkins:通过传统的自由风格(Freestyle)项目或者流水线(Pipeline)来定义任务。在流水线中,使用Groovy脚本编写复杂的构建、测试和部署步骤。例如,定义一个简单的Java项目构建流水线,需要在脚本中指定代码拉取、编译、测试和打包等步骤。

• Argo:主要围绕自定义资源定义(CRD)和工作流模板(Workflow Templates)来构建工作流。它采用声明式的配置方式,通过YAML文件来定义任务之间的依赖关系和执行顺序,更符合Kubernetes原生的配置风格。

与容器生态系统的集成

• Jenkins:可以与容器集成,例如通过在构建节点上运行Docker命令来构建容器镜像,但这种集成相对来说比较手动和复杂。它本身不是为容器原生环境设计的。

• Argo:是为在Kubernetes环境中工作而构建的,与容器生态系统紧密集成。可以很自然地调度和管理容器化的工作负载,并且能够利用Kubernetes的特性,如资源管理、服务发现等。

功能重点

• Jenkins:功能丰富多样,除了构建和部署,还提供了大量的插件用于各种任务,如代码质量检查、安全扫描等。它的插件生态系统是其强大的一个方面,适合多种不同类型的软件开发流程。

• Argo:更侧重于工作流编排和容器原生应用的持续交付。特别适用于在Kubernetes集群内协调复杂的微服务部署、多阶段发布等任务,强调对容器化工作负载的高效管理。

部署和管理

• Jenkins:部署相对简单,可以通过下载WAR包在独立的服务器或者容器中运行。管理方面,需要维护Jenkins服务器本身,包括插件更新、配置备份等。

• Argo:通常部署在Kubernetes集群内,利用Kubernetes的部署和管理机制。这使得它的部署和扩展更符合云原生的方式,但也需要对Kubernetes有一定的了解才能更好地进行部署和维护。

相关推荐
m0_5719575812 分钟前
Java | Leetcode Java题解之第538题把二叉搜索树转换为累加树
java·leetcode·题解
CAORENZHU13 分钟前
Java NIO 核心知识.下
java
程序员徐师兄16 分钟前
基于 JavaWeb 的宠物商城系统(附源码,文档)
java·vue·springboot·宠物·宠物商城
小鸡脚来咯36 分钟前
java 中List 的使用
java·开发语言
牛角上的男孩41 分钟前
部署istio应用未能产生Envoy sidecar代理
云原生·istio
南棱笑笑生42 分钟前
20241105编译Rockchip原厂的Android13并给荣品PRO-RK3566开发板刷机
java·开发语言·前端
Erorrs1 小时前
Android13 系统/用户证书安装相关分析总结(二) 如何增加一个安装系统证书的接口
android·java·数据库
筑梦之路1 小时前
k8s 处理namespace删除一直处于Terminating —— 筑梦之路
云原生·容器·kubernetes
余华余华1 小时前
Ngnix
java
昂子的博客1 小时前
通过mybatis和mybatis plus 实现用户注册功能和基础的增删改查
java·开发语言·mybatis