SpringCloud入门教程:一步步搭建微服务架构
SpringCloud是一组基于SpringBoot的微服务框架,提供服务治理、负载均衡、熔断、配置中心等核心功能,简化了分布式系统的开发与管理。本文详细介绍了SpringCloud的主要组件、优势、应用场景以及快速入门指南。
SpringCloud简介什么是SpringCloud
SpringCloud 是一组基于SpringBoot的微服务框架,它提供了一整套的工具集来简化分布式系统中的常见问题。SpringCloud旨在通过一套一致性的配置来简化分布式系统基础设施的搭建和管理,使得开发者能够更加专注于业务逻辑的开发,而不是底层基础设施的实现细节。SpringCloud的核心功能是围绕着服务治理,支持服务发现、配置中心、负载均衡、熔断器、服务网关等关键组件。
SpringCloud的主要组件
SpringCloud主要由以下组件构成:
- Eureka:服务注册中心,提供服务注册与发现功能。
- Ribbon:客户端负载均衡工具,可以与Feign配合使用。
- Feign:声明式WebService客户端,它使得编写Web服务客户端更加容易。
- Hystrix:容错库,旨在通过添加熔断器、降级处理、服务缓存、服务超时等机制来提高分布式系统的弹性。
- Zuul:一个基于Java的路由和服务网关,它提供动态路由、过滤器、请求合并等功能。
- Config:支持分布式系统的外部化配置。
- SpringCloud Stream:构建消息驱动微服务。
- SpringCloud Bus:将配置数据变更广播到服务网关、API网关等。
- SpringCloud Sleuth:微服务的链路追踪,帮助我们跟踪一个服务调用的整个过程。
- SpringCloud Kubernetes:支持在Kubernetes集群上部署微服务。
SpringCloud的优势和应用场景
优势:
- 简化开发流程:SpringCloud利用SpringBoot的特性,大大简化了微服务的开发、测试、部署等工作,使开发者可以更加专注于业务逻辑的实现。
- 服务治理:SpringCloud提供了服务注册与发现、负载均衡、服务容错等功能,使得服务治理变得简单且高效。
- 弹性伸缩:SpringCloud支持服务的自动注册和发现,提高系统的弹性和可伸缩性。
- 分布式配置:SpringCloud提供集中式、外部化配置,以实现服务端和客户端的统一管理。
- API网关:通过SpringCloud Zuul可以实现API网关。通过一个统一入口点,来管理所有微服务的API,简化客户端与服务器的交互。
- 链路追踪:SpringCloud Sleuth可以追踪整个请求的过程,用于解决分布式系统中的问题调试。
应用场景:
- 电商系统:支持高并发的订单、支付、库存等功能。
- 金融系统:支持交易、风控、数据统计等功能。
- 物流系统:支持订单、配送、仓储等功能。
- 互联网系统:支持广告、社交、门户等功能。
准备开发环境
为了快速入门SpringCloud,首先需要确保本地机器已安装以下软件:
- JDK:Java 8及以上版本。
- Maven:版本3.6.0及以上。
- IDE:推荐IntelliJ IDEA或Eclipse。
- Git:版本管理工具。
- STS:Spring Tool Suite,一个专门为Spring开发者设计的IDE,基于Eclipse。
推荐编程学习网站:慕课网。
创建第一个SpringCloud项目
- 新建一个SpringBoot工程,并添加SpringCloud依赖。在
pom.xml
中添加以下依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 配置Eureka Server。在
application.yml
中添加以下配置:
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
enabled: true
- 创建启动类
EurekaServerApplication
,使用@EnableEurekaServer
注解启用Eureka服务端功能:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 启动
EurekaServerApplication
,访问http://localhost:8761
,可以看到Eureka Server已经成功启动。
项目结构介绍
SpringCloud项目通常包含以下结构:
src/main/java
:存放Java类文件,包括启动类、业务逻辑等。src/main/resources
:存放配置文件,如application.yml
。pom.xml
:项目依赖配置文件。
Eureka服务注册中心的搭建
Eureka服务注册中心是SpringCloud中服务发现的核心组件。通过Eureka,服务提供者可以在Eureka中注册自身,服务消费者可以通过Eureka获取服务提供者的地址列表,并进行服务调用。
- 创建Eureka服务注册中心。使用SpringBoot创建一个新的SpringBoot项目,添加Eureka Server依赖,配置文件
application.yml
如下:
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
enabled: true
- 配置启动类
EurekaServerApplication
启用Eureka Server功能:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
使用Eureka进行服务注册与发现
假设现在需要开发一个服务提供者和一个服务消费者。服务提供者将服务注册到Eureka,服务消费者从Eureka获取服务地址列表。
- 创建服务提供者。在服务提供者中,需要添加Eureka客户端依赖,并配置Eureka相关信息:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8080
spring:
application:
name: service-provider
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
- 创建
ServiceProviderApplication
启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceProviderApplication.class, args);
}
}
- 创建服务消费者。服务消费者也需要添加Eureka客户端依赖,并配置Eureka相关信息:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8081
spring:
application:
name: service-consumer
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
- 创建
ServiceConsumerApplication
启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
}
- 在服务消费者中,使用
RestTemplate
或Feign
进行服务调用。例如,使用RestTemplate
进行服务调用:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ServiceConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer() {
return restTemplate.getForObject("http://SERVICE-PROVIDER/hello", String.class);
}
}
服务注册与发现的实战示例
假设现在有以下需求:创建一个服务提供者ServiceOne
,一个服务消费者ServiceTwo
,以及一个Eureka注册中心。
-
创建Eureka注册中心,参考前面的配置。
-
创建服务提供者
ServiceOne
,参考前面的服务提供者配置。 -
创建服务消费者
ServiceTwo
,参考前面的服务消费者配置。 - 在
ServiceOne
中,添加一个简单的控制器,提供/hello
接口:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceOneController {
@GetMapping("/hello")
public String hello() {
return "Hello from ServiceOne!";
}
}
- 在
ServiceTwo
中,使用RestTemplate
调用ServiceOne
的服务:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ServiceTwoController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer() {
return restTemplate.getForObject("http://SERVICE-ONE/hello", String.class);
}
}
- 启动
EurekaServerApplication
、ServiceProviderApplication
和ServiceConsumerApplication
三个项目,并访问http://localhost:8761
查看服务列表。
配置中心的搭建
SpringCloud Config配置中心提供了集中式的外部化配置,可以支持多种存储方式,包括本地文件、Git、SVN等。这里以Git为例进行介绍。
-
创建一个Git仓库,用于存放配置文件。
- 在SpringCloud Config Server中,配置仓库地址。创建一个SpringBoot项目,添加SpringCloud Config Server依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: ${GIT_URI}
username: ${GIT_USERNAME}
password: ${GIT_PASSWORD}
${GIT_URI}
、${GIT_USERNAME}
、${GIT_PASSWORD}
可以配置成环境变量,也可以直接写死。
- 创建
ConfigServerApplication
启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 在Git仓库中创建配置文件。例如,创建一个配置文件
application.yml
:
spring:
application:
name: service-one
server:
port: 8080
配置文件名格式为<application>-<profile>.yml
,例如service-one.yml
,其中<application>
为应用程序名,<profile>
为配置文件的环境(dev
、test
等)。
分布式配置管理
在微服务架构中,服务提供者和服务消费者可能需要读取不同的配置文件。在SpringCloud Config中,可以通过配置文件的环境属性来实现。
- 在服务提供者中,添加SpringCloud Config客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
配置文件bootstrap.yml
:
spring:
cloud:
config:
uri: http://localhost:8888
application:
name: service-one
profiles:
active: dev
- 在服务消费者中,同样添加SpringCloud Config客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
配置文件bootstrap.yml
:
spring:
cloud:
config:
uri: http://localhost:8888
application:
name: service-two
profiles:
active: dev
- 在服务提供者和服务消费者中,可以通过
@Value
注解或Environment
对象读取配置文件中的属性:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class ServiceOneController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/config")
public String getConfig() {
return appName;
}
}
动态刷新配置
SpringCloud Config支持动态刷新配置,即在不重启应用的情况下,重新加载配置文件。
- 在服务提供者和服务消费者中添加
@RefreshScope
注解:
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class ServiceOneController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/config")
public String getConfig() {
return appName;
}
@GetMapping("/refresh")
public String refreshConfig() {
return new String("Config refreshed");
}
}
- 修改Git仓库中的配置文件,然后在服务提供者和服务消费者中调用
/actuator/refresh
接口进行刷新:
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class ServiceOneController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/config")
public String getConfig() {
return appName;
}
@GetMapping("/refresh")
public String refreshConfig() {
return new String("Config refreshed");
}
}
- 测试配置文件的刷新效果,修改Git仓库中的配置文件,然后访问服务的
/refresh
接口,查看配置的更新情况。
使用Ribbon进行负载均衡
Ribbon是Netflix开源的一个基于HTTP和TCP的客户端负载均衡器,它提供了一系列接口来帮助服务消费者从服务提供者集群中选择出一个要调用的服务实例。
- 在服务提供者和服务消费者中添加Ribbon依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 在服务消费者的
application.yml
中指定服务提供者的Ribbon配置:
server:
port: 8081
spring:
application:
name: service-consumer
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
ribbon:
eager-load:
enabled: true
ConnectTimeout: 5000
ReadTimeout: 5000
listOfServers: localhost:8080,localhost:8082
- 在服务消费者中,使用
RestTemplate
或Feign
进行服务调用,并开启负载均衡:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ServiceConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer() {
return restTemplate.getForObject("http://SERVICE-PROVIDER/hello", String.class);
}
}
使用Hystrix进行服务容错
Hystrix是一个开源的延迟和容错库,用于管理和保护对远程系统、服务和第三方库的访问,防止故障扩散。
- 在服务提供者和服务消费者中添加Hystrix依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 在服务消费者中,使用Hystrix进行服务容错:
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@EnableCircuitBreaker
public class ServiceConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer() {
return restTemplate.getForObject("http://SERVICE-PROVIDER/hello", String.class);
}
}
- 在服务提供者中,模拟服务异常:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceOneController {
@GetMapping("/hello")
public String hello() {
int i = 1 / 0;
return "Hello from ServiceOne!";
}
}
- 观察服务消费者的日志,可以看到Hystrix捕获了远程服务的异常,并进行降级处理。
故障降级和熔断机制介绍
故障降级
在服务消费者中,当远程服务不可用时,可以使用Hystrix进行故障降级。通过在服务消费者中定义一个降级方法,当服务调用失败时,可以返回一个预定义的结果,而不是抛出异常。
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerNotWritableException;
import org.springframework.cloud.client.circuitbreaker.annotation.EnableCircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.annotation.EnableCircuitBreaker;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@EnableCircuitBreaker
public class ServiceConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
@CircuitBreaker(id = "helloService", fallback = "fallback")
public String consumer() {
return restTemplate.getForObject("http://SERVICE-PROVIDER/hello", String.class);
}
public String fallback() {
return "Hello Service is down!";
}
}
熔断机制
在服务消费者中,当远程服务多次调用失败时,可以启用Hystrix的熔断机制。通过设置适当的熔断器阈值,当服务调用失败次数达到阈值时,Hystrix会开启熔断器,阻止后续的服务调用,直到熔断器恢复。
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
circuitBreaker:
requestVolumeThreshold: 10
sleepWindowInMilliseconds: 10000
errorThresholdPercentage: 50
enabled: true
实战案例:完整的SpringCloud微服务项目搭建
项目需求分析
假设现在需要开发一个微服务系统,包含以下几个模块:
- 用户服务(UserService):提供用户相关的操作,如注册、登录、获取用户信息等。
- 商品服务(ProductService):提供商品相关的操作,如查询商品信息、添加商品等。
- 订单服务(OrderService):提供订单相关的操作,如创建订单、查询订单等。
- 配置中心(ConfigServer):集中化管理配置文件。
- 服务注册中心(EurekaServer):提供服务注册与发现功能。
微服务模块设计
- 创建Eureka服务注册中心
EurekaServer
。 - 创建用户服务
UserService
,分为服务提供者和服务消费者。 - 创建商品服务
ProductService
,分为服务提供者和服务消费者。 - 创建订单服务
OrderService
,分为服务提供者和服务消费者。 - 创建配置中心
ConfigServer
,用于管理所有服务的配置文件。
项目搭建与调试
- 创建Eureka服务注册中心。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
enabled: true
启动类EurekaServerApplication
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 创建用户服务
UserService
,分为服务提供者和服务消费者。
服务提供者:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8080
spring:
application:
name: user-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
启动类UserServiceApplication
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
服务消费者:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8081
spring:
application:
name: user-service-consumer
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
启动类UserServiceConsumerApplication
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class UserServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceConsumerApplication.class, args);
}
}
-
创建商品服务
ProductService
和订单服务OrderService
,配置和启动类参考用户服务的配置和启动类。 - 创建配置中心
ConfigServer
。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
配置文件application.yml
:
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: ${GIT_URI}
username: ${GIT_USERNAME}
password: ${GIT_PASSWORD}
启动类ConfigServerApplication
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 在各个服务中添加配置文件,并在
bootstrap.yml
中配置访问ConfigServer。
spring:
cloud:
config:
uri: http://localhost:8888
application:
name: <service-name>
profiles:
active: dev
调试项目:
- 启动
EurekaServerApplication
。 - 启动
ConfigServerApplication
。 - 启动各个服务的服务提供者和服务消费者。
- 访问
http://localhost:8761
查看服务注册情况。 - 访问各个服务的API,测试服务调用。
至此,一个简单的SpringCloud微服务项目已经搭建完成。
共同学习,写下你的评论
评论加载中...
作者其他优质文章