教程

Spring Cloud Load Balancer 指南

1、简介 随着微服务架构越来越流行,在不同服务器上运行多个服务变得越来越普遍。本文将带你了解如何使用 Spring Cloud Load Balancer(负载均衡器) 创建容错性更强的应用。 2、负载均衡是什么? 负载均衡是在同一应用的不同实例之间分配流量的过程。 为了容错,每个应用通常都要运行多个实例。因此,当一个服务需要与另一个服务通信时,它需要选择一个特定的实例来发送请求。 负载均衡,有很多算法: 随机选择:随机选择一个实例 循环:每次按相同顺序选择实例 最少连接:选择当前连接最少的实例 权重指标:使用权重指标选择最佳实例(例如 CPU 或内存使用率) IP 哈希(Hash):使用客户端 IP 的哈希值映射到实例 以上只是负载均衡算法的几个例子,每种算法都有其优缺点。 随机选择和轮循很容易实现,但可能无法优化服务的使用。相反,最少连接和权重指标比较复杂,但通常能创造更优化的服务利用率。IP 哈希可以保证客户端每次都命中同一台实例,意味着实例可以保存一些客户端的状态信息,但它的容错性不强。 3、Spring Cloud Load Balancer 简介 Spring Cloud Load Balancer 用来创建以负载均衡方式与其他应用通信的应用。可以使用任意算法,在进行远程服务调用时轻松实现负载均衡。 接下来,我们通过实例来进行说明。首先,创建一个简单的服务器应用。服务器只有一个 HTTP 端点,可以作为多个实例运行。 然后,创建一个客户端应用,使用 Spring Cloud Load Balancer 在服务器的不同实例之间轮流发送请求。 3.1、示例服务器 创建一个简单的 Spring Boot 应用: @SpringBootApplication @RestController public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } @Value("${server.instance.id}") String instanceId; @GetMapping("/hello") public String hello() { return String.

JUnit 测试时加载 ApplicationContext 失败

1、概览 在 Spring Boot 应用中,可以同时包含基于注解和基于 XML 的配置来混合定义 Bean。在这种环境中,如果你在测试类中使用基于 XML 的配置可能会遇到 “Failed to load ApplicationContext” 异常。因为 Application Context 没有加载到 Test Context 中。 本文将会带你了解如何把 XML Application Context 集成到 Spring Boot 应用的测试中。 2、“Failed to load ApplicationContext” 异常 在 Spring Boot 应用中集成基于 XML 的 Application Context 来重现该异常。 首先,假设有一个包含 Service Bean 定义的 application-context.xml 文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="employeeServiceImpl" class="com.baeldung.xmlapplicationcontext.service.EmployeeServiceImpl" /> </beans> 在 webapp/WEB-INF/ 位置添加 application-context.xml 文件: 再创建一个 Service 接口和实现类:

Spring Cloud Gateway 和 Oauth2

1、概览 Spring Cloud Gateway 是一个响应式的轻量级网关,是 Spring Cloud 体系中一个比较重要的组件。本文将带你了解如何在其基础上快速实现 OAuth 2.0 认证、授权。 2、OAuth 2.0 快速回顾 OAuth 2.0 标准是一个成熟的标准,在互联网上广泛使用,是用户和应用安全访问资源的一种安全机制。 其中涉及的关键术语如下: Resource(资源):只有经过授权的客户端才能检索的任何类型的信息。 Client(客户端):消费资源的应用,通常通过 REST API 消费资源。 Resource Server(资源服务器):负责向授权客户端提供资源的服务。 Resource Owner(资源所有者):实体(人或应用),拥有资源,并最终负责向客户端授予对该资源的访问权限。 Token(令牌):客户端获取的一段信息,并作为请求的一部分发送给资源服务器以进行身份验证。 Identity Provider(身份提供商,即 IDP):验证用户凭证并向客户端发放 Access Token。 Authentication Flow(认证模式/流程):客户端获得有效 Token 必须经过的一系列步骤。 你可以通过 Auth0 的相关文档了解更多详细内容。 3、OAuth 2.0 模式 Spring Cloud Gateway 主要用于以下用途之一: OAuth Client(客户端) OAuth Resource Server(资源服务器) 我们来逐个了解。 3.1、Spring Cloud Gateway 作为 OAuth 2.0 客户端 在这种情况下,任何未经身份认证的传入请求都将触发授权码流程。一旦网关获取到 Token,它将在向后端服务发起请求时使用该 Token。 在实际应用中,一个很好的例子是聚合了 “社交应用” 的应用:对于每个支持的社交应用,网关将充当 OAuth 2.0 客户端。 因此,前端(通常是使用 Angular、React 或类似 UI 框架构建的 SPA 应用)可以代表终端户无缝访问这些应用上的数据。更重要的是:用户无需暴露自己的凭证。

在 Swagger 文档中移除 BasicErrorController

1、概览 本文将带你了解如何 Swagger 文档界面中隐藏 BasicErrorController。 3、问题 如果应用中包含了一个 BasicErrorController,Swagger 默认会将其所有端点也包含在生成的文档中。 我们需要提供自定义配置来移除不需要的 Controller。 例如,项目中的 Rest Controller 如下: @RestController @RequestMapping("good-path") public class RegularRestController { @ApiOperation(value = "This method is used to get the author name.") @GetMapping("/getAuthor") public String getAuthor() { return "Name Surname"; } } 另外,还包含一个继承 BasicErrorController 的 Error Controller: @Component @RequestMapping("my-error-controller") public class MyErrorController extends BasicErrorController { // basic constructor } 启动应用,访问文档!你可以看到,my-error-controller 包含在生成的文档中: 4、解决办法 有四种方式可以从 Swagger 文档中排除资源。 4.1、通过 basePackage() 方法排除 通过指定 Controller 所在的包,可以排除其他不需要的资源。

Spring Cloud Sleuth 获取当前 Trace ID

1、概览 本文将带你了解 Spring Cloud Sleuth,以及如何在 Spring Boot 中使用它进行链路追踪。 它可以在日志中添加额外有用的信息,并通过唯一链路 ID 帮助 Debug。这些操作在 Sleuth 术语中称为追踪(Trace)。它们可以由多个步骤组成,称为 Span。 例如,链路追踪可以是一个从应用中查询数据的 GET 请求。当应用处理该请求时,可以将其分割成更小的步骤:用户授权、执行数据库查询、转换响应。每个步骤都是属于同一链路追踪的唯一 Span。 在某些情况下,我们可能需要获取当前 Trace 或 Span 的 ID。例如,当发生事故时,我们可以将这些信息发送给开发团队。然后,他们就可以用它来调试和解决问题。 2、应用设置 创建一个 Spring Boot 项目,并添加 spring-cloud-starter-sleuth dependency 依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <version>3.1.0</version> </dependency> 此 Starter 可与 Spring Boot 完美集成,并提供 Spring Cloud Sleuth 开箱即用的配置。 接下来,在 application.properties 文件中设置应用名称,这样就能在日志中看到该名称以及 Trace 和 Span ID: spring.application.name=Baeldung Sleuth Tutorial 现在,创建一个 REST Controller,提供一个 GET 端点: @RestController public class SleuthTraceIdController { @GetMapping("/traceid") public String getSleuthTraceId() { return "Hello from Sleuth"; } } 启动应用后访问这个 API 端点 http://localhost:8080/traceid,你可以看到响应:Hello from Sleuth。

自定义 Zuul Exception

1、概览 Zuul 是 Netflix 推出的基于 JVM 的网关和服务器端负载均衡器。Zuul 的规则引擎提供了灵活性,可以编写规则和过滤器(Filter)来增强在 Spring Cloud 微服务架构中的路由功能。。 本文将会带你了解如何通过自定义 Error Filter 来自定义 Zuul 中的异常和 Error 响应。当代码执行过程中发生错误时,这些自定义 Error Filter 将被执行。 2、Zuul 异常 Zuul 中处理的所有异常都是 ZuulException。 ZuulException 不能通过 @ControllerAdvice 捕获,也不能通过 @ExceptionHandling 对方法进行注解。这是因为 ZuulException 是由 Error Filter 抛出的。因此,它会跳过后续的过滤链,永远不会到达 Error Controller。下图描述了 Zuul 中错误处理的层次结构: 出现 ZuulException 时,Zuul 会显示以下错误响应: { "timestamp": "2022-01-23T22:43:43.126+00:00", "status": 500, "error": "Internal Server Error" } 在某些情况下,可能需要自定义 ZuulException 响应中的错误信息或状态码。这时,Zuul Filter 就能派上用场了。 3、自定义 Zuul 异常 spring-cloud-starter-netflix-zuul Starter 包括三种 Filter:Pre(前置)、Post(后置)和 Error(错误)。 本文重点深入了解 Error Filter。

Spring Boot 异常:HttpMessageNotWritableException: No Converter for [class ...] With Preset Content-Type

1、概览 本文将带你了解 “HttpMessageNotWritableException: no converter for [class …] with preset Content-Type” 异常的原因以及解决办法。 2、原因 异常的堆栈信息说明了一切:Spring 找不到合适的 HttpMessageConverter,无法将 Java 对象转换为 HTTP 响应。 Spring 依靠客户端的 Accept Header 来检测它需要响应的媒体类型(Media Type)。 因此,使用未预注册消息转换器(Message Converter)的 Media Type 将导致 Spring 抛出异常。 3、重现异常 通过一个实际例子来重现异常。 创建一个 Handler Method,指定一种媒体 Media Type(用于响应),这种类型没有注册 HttpMessageConverter。 例如,使用 MediaType.APPLICATION_XML_VALUE 或字符串 application/xml: @GetMapping(value = "/student/v3/{id}", produces = MediaType.APPLICATION_XML_VALUE) public ResponseEntity<Student> getV3(@PathVariable("id") int id) { return ResponseEntity.ok(new Student(id, "Robert", "Miller", "BB")); } 接着,使用 cURL 对 http://localhost:8080/api/student/v3/1 发起请求: curl http://localhost:8080/api/student/v3/1 端点响应如下:

在 Spring Boot 中配置和使用多个数据源

1、概览 一般的 Spring Boot 应用通常只需要配置一个数据库,但是有时也可能需要访问多个数据源。本文将带你了解如何在 Spring Boot 中配置和使用多个数据源。 2、默认行为 通常,我们会在 application.yml 中声明 Spring Boot 数据源,如下: spring: datasource: url: ... username: ... password: ... driverClassname: ... Spring 会将这些配置映射到 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 的实例。 DataSourceProperties 的定义如下: @ConfigurationProperties(prefix = "spring.datasource") public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean { // ... /** * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. */ private String driverClassName; /** * JDBC URL of the database. */ private String url; /** * Login username of the database.

Spring Boot 发送邮件

Spring Boot 对于发送邮件这种常用功能也提供了开箱即用的 Starter:spring-boot-starter-mail。 通过这个 starter,只需要简单的几行配置就可以在 Spring Boot 中实现邮件发送,可用于发送验证码、账户激活等等业务场景。 本文将通过实际的案例带你了解如何在 Spring Boot 中使用 QQ 邮箱发送邮件。 关于 Spring 对邮件支持的更多细节,你可以参阅 中文文档。 创建 Spring Boot 应用 在 pom.xml 中添加 spring-boot-starter-mail 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> 属性配置 在 application.yaml 中配置属性。 spring: mail: # 指定邮件服务器地址 host: smtp.qq.com # 登录账户 username: 747692844@qq.com # 登录密码 password: "<你的密码/授权码>" # 端口 port: 465 # 默认编码 default-encoding: UTF-8 # 使用的协议 protocol: smtps # 其他的属性 properties: "mail.smtp.connectiontimeout": 5000 "mail.smtp.timeout": 3000 "mail.smtp.writetimeout": 5000 "mail.

Spring Cloud Config 使用 GIT 以外的配置源

1、简介 Spring Cloud Config 是 Spring Cloud 生态下的一个子项目,可让 Spring 应用轻松实现配置外部化。通过它,可以将配置数据作为服务暴露出来,从而使得任何具有 HTTP 客户端的应用都可以轻松地获取配置数据。 本文将会带你了解如何在 Spring Cloud Config 中使用 Git 以外的配置源来存储配置信息。 2、Spring Cloud Config 概览 Spring Cloud Config 采用了典型的客户端-服务器模型。集中式服务器(或多个服务器)从外部数据源读取配置数据。这些服务器会暴露各种 HTTP 端点,允许任何其他应用查询配置数据。 Spring Cloud Config 还能让 Spring Boot 应用非常方便地自动连接到配置服务器。服务器提供的配置数据可以像客户端应用中的其他属性源一样使用。 3、GIT Spring Cloud Config 最常见的使用案例是在 git 仓库中存储配置数据。这种方式的设置有几个优点: 灵活性:git 仓库可以容纳各种类型的文件,包括二进制文件。 安全性:可轻松控制细粒度的读写权限。 审计:强大的历史跟踪功能可轻松审核配置更改。 标准化:无论哪家提供商(Provider),Git 操作都是标准的,这意味着我们可以自行托管或使用任意数量的第三方提供商。 分布式: Git 从一开始就是为分布式设计的,因此非常适合云原生和微服务架构。 尽管有上述种种好处,但 git 并不总是存储配置数据的最佳选择。例如,项目可能已经将配置数据放在其他数据存储(如关系型数据库)中。在这种情况下,将其迁移到 git 可能就得不偿失了。 4、使用 GIT 以外的 配置源 在 Spring Cloud Config 中使用 git 以外的其他配置源时时,指的其实是服务器组件。对数据存储的选择不会影响客户端组件。只有服务器会受到影响。 在 Spring Cloud Config Server 库中,有一个名为 EnvironmentRepository 的接口定义了一个配置源。所有配置源(包括 git 和其他配置源)都必须实现该接口。