文章目录
1. 微服务架构概述
微服务架构是一种将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,并通过轻量级机制(通常是HTTP API)进行通信。Spring Boot为微服务架构提供了完整的解决方案。
1.1 微服务架构特点
- 服务拆分:按业务功能拆分服务
- 独立部署:每个服务独立部署和扩展
- 技术多样性:不同服务可以使用不同技术栈
- 容错性:单个服务故障不影响整体系统
- 可扩展性:可以独立扩展高负载服务
1.2 微服务技术栈
- Spring Cloud:微服务开发框架
- 服务注册与发现:Eureka、Consul、Nacos
- 配置中心:Spring Cloud Config、Nacos
- 服务网关:Spring Cloud Gateway、Zuul
- 负载均衡:Ribbon、LoadBalancer
- 熔断器:Hystrix、Resilience4j
- 消息队列:RabbitMQ、Kafka
1.3 核心依赖
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<!-- Eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Spring Cloud Config Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Resilience4j -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
</dependencies>
2. 服务注册与发现
2.1 Eureka服务端
package com.example.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);
}
}
application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
2.2 Eureka客户端
package com.example.userservice;
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);
}
}
application.yml
server:
port: 8081
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
3. 服务间通信
3.1 OpenFeign客户端
package com.example.userservice.client;
import com.example.userservice.dto.OrderDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@FeignClient(name = "order-service")
public interface OrderServiceClient {
@GetMapping("/orders/user/{userId}")
List<OrderDto> getUserOrders(@PathVariable Long userId);
@GetMapping("/orders/{orderId}")
OrderDto getOrderById(@PathVariable Long orderId);
}
3.2 服务调用
package com.example.userservice.service;
import com.example.userservice.client.OrderServiceClient;
import com.example.userservice.dto.OrderDto;
import com.example.userservice.dto.UserDto;
import com.example.userservice.entity.User;
import com.example.userservice.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderServiceClient orderServiceClient;
public UserDto getUserWithOrders(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
List<OrderDto> orders = orderServiceClient.getUserOrders(userId);
UserDto userDto = new UserDto();
userDto.setId(user.getId());
userDto.setUsername(user.getUsername());
userDto.setEmail(user.getEmail());
userDto.setOrders(orders);
return userDto;
}
}
4. 服务网关
4.1 Gateway配置
package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
application.yml
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=2
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=2
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
4.2 自定义过滤器
package com.example.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalGatewayFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class AuthFilter implements GlobalGatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 验证token逻辑
if (!isValidToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
private boolean isValidToken(String token) {
// 实现token验证逻辑
return true;
}
@Override
public int getOrder() {
return -1;
}
}
5. 配置中心
5.1 Config Server
package com.example.configserver;
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);
}
}
application.yml
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-repo/config-repo
search-paths: config
5.2 Config Client
# bootstrap.yml
spring:
application:
name: user-service
cloud:
config:
uri: http://localhost:8888
fail-fast: true
6. 熔断器
6.1 Resilience4j配置
resilience4j:
circuitbreaker:
instances:
orderService:
failure-rate-threshold: 50
wait-duration-in-open-state: 30s
sliding-window-size: 10
minimum-number-of-calls: 5
retry:
instances:
orderService:
max-attempts: 3
wait-duration: 1s
timelimiter:
instances:
orderService:
timeout-duration: 3s
6.2 熔断器使用
package com.example.userservice.service;
import com.example.userservice.client.OrderServiceClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
public class ResilientUserService {
@Autowired
private OrderServiceClient orderServiceClient;
@CircuitBreaker(name = "orderService", fallbackMethod = "getUserOrdersFallback")
@Retry(name = "orderService")
@TimeLimiter(name = "orderService")
public CompletableFuture<List<OrderDto>> getUserOrders(Long userId) {
return CompletableFuture.supplyAsync(() ->
orderServiceClient.getUserOrders(userId));
}
public CompletableFuture<List<OrderDto>> getUserOrdersFallback(Long userId, Exception ex) {
// 返回默认订单或缓存数据
return CompletableFuture.completedFuture(List.of());
}
}
7. 消息队列
7.1 RabbitMQ配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
7.2 消息生产者
package com.example.userservice.messaging;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserEventPublisher {
@Autowired
private RabbitTemplate rabbitTemplate;
public void publishUserCreatedEvent(UserCreatedEvent event) {
rabbitTemplate.convertAndSend("user.exchange", "user.created", event);
}
public void publishUserUpdatedEvent(UserUpdatedEvent event) {
rabbitTemplate.convertAndSend("user.exchange", "user.updated", event);
}
}
7.3 消息消费者
package com.example.orderservice.messaging;
import com.example.orderservice.service.OrderService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserEventConsumer {
@Autowired
private OrderService orderService;
@RabbitListener(queues = "user.created.queue")
public void handleUserCreated(UserCreatedEvent event) {
// 处理用户创建事件
orderService.createUserProfile(event.getUserId());
}
@RabbitListener(queues = "user.updated.queue")
public void handleUserUpdated(UserUpdatedEvent event) {
// 处理用户更新事件
orderService.updateUserProfile(event.getUserId(), event.getUserData());
}
}
8. 分布式追踪
8.1 Sleuth配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
8.2 追踪配置
spring:
sleuth:
sampler:
probability: 1.0
zipkin:
base-url: http://localhost:9411
9. 服务监控
9.1 Actuator配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
metrics:
export:
prometheus:
enabled: true
9.2 健康检查
package com.example.userservice.health;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
@Autowired
private UserRepository userRepository;
@Override
public Health health() {
try {
userRepository.count();
return Health.up()
.withDetail("database", "Available")
.build();
} catch (Exception e) {
return Health.down()
.withDetail("database", "Unavailable")
.withDetail("error", e.getMessage())
.build();
}
}
}
10. 容器化部署
10.1 Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/user-service-1.0.0.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "app.jar"]
10.2 Docker Compose
version: '3.8'
services:
eureka-server:
image: eureka-server:latest
ports:
- "8761:8761"
environment:
- SPRING_PROFILES_ACTIVE=docker
user-service:
image: user-service:latest
ports:
- "8081:8081"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka/
depends_on:
- eureka-server
order-service:
image: order-service:latest
ports:
- "8082:8082"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka/
depends_on:
- eureka-server
api-gateway:
image: api-gateway:latest
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka/
depends_on:
- eureka-server
11. 总结
Spring Boot微服务架构提供了完整的微服务开发解决方案:
- 服务注册与发现:Eureka、Consul等服务注册中心
- 服务间通信:OpenFeign、RestTemplate等通信方式
- 服务网关:Spring Cloud Gateway统一入口
- 配置中心:Spring Cloud Config集中配置管理
- 熔断器:Resilience4j、Hystrix容错处理
- 消息队列:RabbitMQ、Kafka异步通信
- 分布式追踪:Sleuth、Zipkin链路追踪
- 服务监控:Actuator、Micrometer监控
- 容器化部署:Docker、Kubernetes部署
通过合理使用这些技术,可以构建出高可用、可扩展的微服务系统。
305

被折叠的 条评论
为什么被折叠?



