微服务与分布式系统是现代Java开发的趋势,解决传统单体应用的扩展性和维护性问题。本篇将从微服务基础、Spring Cloud核心组件到分布式一致性,系统讲解相关技术,助你在面试中展现架构设计和分布式问题解决能力。
微服务将应用拆分为小型独立服务,围绕业务能力构建。
核心特性
- 独立部署: 每个服务单独运行和更新。
- 松耦合: 服务间通过API通信(如REST、gRPC)。
- 技术异构: 可使用不同语言和数据库。
优点与挑战
- 优点:高扩展性、易维护。
- 挑战:分布式复杂性(如一致性、网络延迟)。
面试问题:
- 问题: 微服务与单体应用的区别?
- 答案: 微服务按业务拆分,独立部署,松耦合;单体应用集中式开发部署,紧耦合,扩展性差。
Spring Cloud为微服务提供了丰富的工具集。
示例: Eureka服务注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| // 服务端配置 (application.yml)
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
port: 8761
// 服务端主类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// 客户端配置 (application.yml)
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
// 客户端主类
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class UserServiceApplication {
@GetMapping("/user")
public String getUser() {
return "User from " + InetAddress.getLocalHost().getHostName();
}
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
|
面试问题:
- 问题: Eureka的工作原理是什么?
- 答案: 服务启动时注册到Eureka Server,客户端通过心跳维持状态,Eureka提供服务列表供发现。
Spring Cloud Config提供集中式配置管理。
- 原理
- 配置存储在Git仓库,服务动态拉取。
- 支持刷新(
@RefreshScope
)。
示例: 配置客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| // application.yml
spring:
application:
name: config-client
cloud:
config:
uri: http://localhost:8888
management:
endpoints:
web:
exposure:
include: refresh
// 主类
@SpringBootApplication
@RestController
@RefreshScope
public class ConfigClientApplication {
@Value("${app.message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
|
面试问题:
- 问题: 如何实现配置动态刷新?
- 答案: 使用
@RefreshScope
注解,调用/actuator/refresh
端点触发更新。
分布式追踪记录请求在服务间的传播。
- Sleuth: 添加Trace ID和Span ID。
- Zipkin: 收集和可视化追踪数据。
配置: 添加依赖并配置
1
2
3
4
5
6
7
8
| <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
|
application.yml
:
1
2
3
4
5
6
| spring:
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1.0 # 100%采样
|
面试问题:
- 问题: 分布式追踪的作用是什么?
- 答案: 追踪请求路径,定位延迟或故障,优化系统性能。
分布式系统需在CAP(一致性、可用性、分区容忍性)中权衡。
CAP选择
- CP: 强一致性(如分布式锁)。
- AP: 高可用性(如最终一致性)。
一致性方案
- 分布式锁: Redis实现。
- 2PC/3PC: 事务协调。
- BASE: 柔性事务(如TCC)。
示例: Redis分布式锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| import redis.clients.jedis.Jedis;
public class DistributedLockDemo {
public static boolean acquireLock(Jedis jedis, String lockKey, String value, int expireMs) {
return "OK".equals(jedis.set(lockKey, value, "NX", "PX", expireMs));
}
public static void releaseLock(Jedis jedis, String lockKey) {
jedis.del(lockKey);
}
public static void main(String[] args) throws Exception {
try (Jedis jedis = new Jedis("localhost", 6379)) {
String lockKey = "lock:resource";
if (acquireLock(jedis, lockKey, "client1", 10000)) {
System.out.println("Lock acquired");
Thread.sleep(1000);
releaseLock(jedis, lockKey);
System.out.println("Lock released");
} else {
System.out.println("Failed to acquire lock");
}
}
}
}
|
面试问题:
- 问题: 如何保证分布式数据一致性?
- 答案: 使用分布式锁确保顺序操作,或通过最终一致性(如消息队列+补偿机制)实现。
- 实践: 搭建Eureka和Gateway微服务集群。
- 深入: 阅读Spring Cloud源码,如
EurekaClient
。 - 表达: 用架构图解释微服务通信流程。
微服务与分布式系统是现代Java开发的热点,掌握Spring Cloud和一致性方案,能让你在面试中展现架构能力。下一专题将探讨设计模式与代码优化,敬请期待!