跳转到内容
云栖回顾 | 2024 云栖大会微服务和网关相关演讲材料点此了解

Spring Boot 单体应用升级 Spring Cloud 微服务最佳实践

Spring Cloud 是在 Spring Boot 之上构建的一套微服务生态体系,包括服务发现、配置中心、限流降级、分布式事务、异步消息等,因此通过增加依赖、注解等简单的四步即可完成 Spring Boot 应用到 Spring Cloud 升级。

Spring Boot 应用升级为 Spring Cloud

以下是应用升级 Spring Cloud 的完整步骤。

第一步:添加 Spring Cloud 依赖

首先,为应用添加 Spring CloudSpring Cloud Alibaba 依赖。注意根据当前应用 Spring Boot 版本选择合适的 Spring Cloud 版本,具体参见版本映射表

<properties>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
<spring-cloud.version>2022.0.0</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 服务发现:OpenFeign服务调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 负载均衡器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>

以上我们添加了服务注册发现OpenFeign 等依赖。

第二步:添加配置

在应用 application.yml或者 application.properties文件中增加以下配置项,设置应用名、注册中心地址。

application.yml

spring:
application:
#项目名称必填,在注册中心唯一
#最好和之前域名规范、kubernetes service名等保持一致(会作为调用)
name: service-provider
cloud:
nacos:
discovery: #启用 spring cloud nacos discovery
server-addr: 127.0.0.1:8848

application.properties

#项目名称必填,在注册中心唯一;最好和之前域名规范保持一致,第四步会讲到原因
spring.application.name=service-provider
#启用 spring cloud nacos discovery
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

第三步:启动类增加注解

启动类增加 EnableDiscoveryClient EnableFeignClients 注解,启动服务地址自动注册与发现。

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}

第四步:调整服务调用方式

注意!

  1. 为了保证平滑升级,请确保下游应用完成 Spring Cloud 改造并在注册中心注册服务后再进行调用方式改造。
  2. RestTemplate/FeignClient 默认发起调用的 hostname (示例中的service-provider) 是对端 Spring Cloud 应用名。因此,为了保证尽可能少的改造量,改造过程中设置的应用名 spring.name=service-provider 最好和之前的命名规范保持一致。比如:
    • 如果之前有自定义域名,则和域名定义保持一致
    • 如果之前用的 Kubernetes Service,则和 Service Name 保持一致
  1. RestTemplate 模式

为之前的 RestTemplate Bean 添加 @LoadBlanced 注解,使得 RestTemplate 接入服务发现与负载均衡:

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

其它原有 RestTemplate 发起调用的代码保持不变,只需调整 hostname 即可,如下所示。

@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/echo-rest/{str}")
public String rest(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
}
}
  1. FeignClient 模式

使用 @FeignClient 注解将 EchoService 这个接口包装成一个 FeignClient,属性 name 对应对端应用名 spring.name=service-provider

//@FeignClient(name = "service-provider", url="http://service.example.com/")
@FeignClient(name = "service-provider")
public interface EchoService {
@GetMapping(value = "/echo/{str}")
String echo(@PathVariable("str") String str);
}

将 EchoService 作为标准 bean 注入,即可对远端服务发起请求了。

@RestController
public class TestController {
@Autowired
private EchoService echoService;
@GetMapping(value = "/echo-feign/{str}")
public String feign(@PathVariable String str) {
return echoService.echo(str);
}
}
  1. HtClient、自定义HTTP访问工具等

对于使用 HttpClient 或者自行封装 http 调用工具的用户,建议统一改造为以上 1、2 两种调用模式之一。

参考资料

完整示例源码

基于 Spring Boot 构建的应用架构变化多样,比如可能是以下一些常用架构的任意一种,但不论哪种架构,升级 Spring Cloud 的大致改造方式都是类似的(都可以转为基于 Nacos 注册中心的地址发现与负载均衡)。

  • 基于 DNS 自定义域名,服务间的通过域名调用实现负载均衡
  • 基于 SLB 的中心化流量转发,调用直接转发到 SLB,由 SLB 实现在服务间实现流量转发
  • 基于 Kubernetes Service 微服务体系,依赖 Kubernetes ClusterIP 等实现负载均衡与调用转发

在此,我们以 DNS 自定义域名架构为例,提供了一个 Spring Boot 到 Spring Cloud 升级改造的完整示例,升级前后的应用架构图如下。具体可参见 Github 源码链接

spring boot 升级前 SpringBoot 架构 👆

spring cloud _升级后 SpringCloud 架构 _👆

Spring Boot 与 Spring Cloud Alibaba 版本对应关系

请根据您使用的 Spring Boot 版本,选择兼容的 Spring Cloud Alibaba 版本

Spring Boot VersionSpring Cloud Alibaba VersionSpring Cloud Version
3.0.22022.0.0.0Spring Cloud 2022.0.0
3.0.22022.0.0.0-RC2Spring Cloud 2022.0.0
3.0.02022.0.0.0-RC1Spring Cloud 2022.0.0
2.6.132021.0.5.0Spring Cloud 2021.0.5
2.6.112021.0.4.0Spring Cloud 2021.0.4
2.6.32021.0.1.0Spring Cloud 2021.0.1
2.4.22021.1Spring Cloud 2020.0.1
2.3.12.RELEASE2.2.10-RC1Spring Cloud Hoxton.SR12
2.3.12.RELEASE2.2.9.RELEASESpring Cloud Hoxton.SR12
2.3.12.RELEASE2.2.8.RELEASESpring Cloud Hoxton.SR12
2.3.12.RELEASE2.2.7.RELEASESpring Cloud Hoxton.SR12
2.3.2.RELEASE2.2.6.RELEASESpring Cloud Hoxton.SR9
2.2.5.RELEASE2.2.1.RELEASESpring Cloud Hoxton.SR3
2.2.X.RELEASE2.2.0.RELEASESpring Cloud Hoxton.RELEASE
2.1.13.RELEASE2.1.4.RELEASESpring Cloud Greenwich.SR6
2.1.X.RELEASE2.1.2.RELEASESpring Cloud Greenwich
2.0.X.RELEASE2.0.4.RELEASE(停止维护,建议升级)Spring Cloud Finchley
1.5.X.RELEASE1.5.1.RELEASE(停止维护,建议升级)Spring Cloud Edgware

Spring Cloud Alibaba Starters 列表与使用手册

Spring Cloud Alibaba 集成的组件版本

每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version
2022.0.0.01.8.62.2.14.9.4~1.7.0
2022.0.0.0-RC21.8.62.2.14.9.4~1.7.0-native-rc2
2021.0.5.01.8.62.2.04.9.4~1.6.1
2.2.10-RC11.8.62.2.04.9.4~1.6.1
2022.0.0.0-RC11.8.62.2.1-RC4.9.4~1.6.1
2.2.9.RELEASE1.8.52.1.04.9.4~1.5.2
2021.0.4.01.8.52.0.44.9.4~1.5.2
2.2.8.RELEASE1.8.42.1.04.9.3~1.5.1
2021.0.1.01.8.31.4.24.9.2~1.4.2
2.2.7.RELEASE1.8.12.0.34.6.12.7.131.3.0
2.2.6.RELEASE1.8.11.4.24.4.02.7.81.3.0
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE1.8.01.4.14.4.02.7.81.3.0
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE1.8.01.3.34.4.02.7.81.3.0
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE1.7.11.2.14.4.02.7.61.2.0
2.2.0.RELEASE1.7.11.1.44.4.02.7.4.11.0.0
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE1.7.01.1.44.4.02.7.30.9.0
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE1.6.31.1.14.4.02.7.30.7.1