微服务架构是一种软件开发方法,将一个应用拆分为多个小型、独立的服务,每个服务只负责一个特定的功能。这些服务可以独立部署、扩展和维护,通常通过轻量级通信机制(如HTTP API或消息队列)进行通信。微服务架构可以帮助提高系统的灵活性、可扩展性和可靠性。
微服务架构的特点包括:
服务自治:每个服务都可以独立部署、开发、测试和扩展。
去中心化数据管理:每个服务拥有自己的数据库或数据源,服务之间不会共享数据。
松耦合:服务之间通过API进行通信,降低了服务之间的依赖。
弹性扩展:可以根据不同服务的需求进行独立扩展,而不必扩展整个系统。
技术异构性:每个微服务可以使用不同的技术栈,开发团队可以选择最合适的技术。
故障隔离:某个微服务的故障不会影响到整个系统。
本文介绍了微服务架构常用的几种设计模式及其代码示例。
一 API Gateway 模式
API Gateway 是微服务系统中的单一入口。客户端不直接与各个微服务通信,而是通过 API Gateway 进行请求分发和聚合。API Gateway 还可以提供额外的功能,比如身份认证、负载均衡、日志记录等。
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("service1_route", r -> r.path("/service1/**")
.uri("http://localhost:8081"))
.route("service2_route", r -> r.path("/service2/**")
.uri("http://localhost:8082"))
.build();
}
}
在该例中,使用 Spring Cloud Gateway
来实现API Gateway,通过路由将客户端请求分发到不同的微服务。客户端访问 /service1/
的请求会被转发到 localhost:8081
,而 /service2/
会被转发到 localhost:8082
。
二 Service Discovery(服务发现)模式
微服务可能动态扩展或缩减,服务发现模式通过一个注册中心动态发现服务实例,使微服务能够自动找到彼此。常见的服务发现工具包括 Eureka、Consul 等。
服务注册中心 (Eureka Server):
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
微服务注册到 Eureka:
@SpringBootApplication
@EnableEurekaClient
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
在本例中,@EnableEurekaServer
启用 Eureka 作为服务注册中心,微服务通过 @EnableEurekaClient
注册到 Eureka 以实现自动发现。
三 Circuit Breaker(断路器)模式
断路器模式用于防止服务之间的故障传递。当一个微服务出现故障或响应缓慢时,断路器可以及时切断请求,防止过多请求压垮下游服务。
@RestController
public class MyController {
@GetMapping("/callService")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public String callService() {
// 调用远程服务
String response = restTemplate.getForObject("http://service-url", String.class);
return response;
}
public String fallbackMethod() {
return "服务不可用,请稍后重试";
}
}
@HystrixCommand
用于标记需要使用断路器的服务调用,如果远程服务不可用,会调用 fallbackMethod
进行降级处理。
四 Database per Service(独立数据库)
在微服务架构中,每个微服务都拥有自己的数据库,这样可以避免多个服务共享数据库时的耦合。各个服务独立管理自己的数据,且只能通过 API 访问其他服务的数据。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double price;
}
public interface ProductRepository extends JpaRepository<Product, Long> {
}
@RestController
public class ProductController {
@Autowired
private ProductRepository productRepository;
@GetMapping("/products")
public List<Product> getAllProducts() {
return productRepository.findAll();
}
}
每个微服务有自己的数据模型(Product
),并且管理自己的数据库连接,使用 Spring Data JPA
管理数据的增删改查。
五 Event-Driven(事件驱动)模式
事件驱动模式下,微服务之间通过事件异步通信。一个微服务可以发布事件,其他微服务可以订阅这些事件,实现松耦合。
@EnableBinding(Source.class)
public class EventProducer {
@Autowired
private MessageChannel output;
public void publishEvent(String data) {
output.send(MessageBuilder.withPayload(data).build());
}
}
@EnableBinding(Sink.class)
public class EventConsumer {
@StreamListener(Sink.INPUT)
public void handleEvent(String data) {
System.out.println("Received event: " + data);
}
}
使用 Spring Cloud Stream
来实现事件驱动的微服务架构,EventProducer
发布事件,EventConsumer
订阅事件。
六 Aggregator(聚合器)模式
在一些场景下,一个客户端请求可能需要调用多个微服务来获取所需的数据。Aggregator(聚合器)模式允许一个微服务负责调用多个其他微服务,聚合数据并返回给客户端。这样可以减少客户端的复杂性,避免客户端直接与多个微服务交互。
@RestController
public class AggregatorController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/aggregate")
public AggregatedResponse aggregateData() {
// 调用多个微服务获取数据
String service1Data = restTemplate.getForObject("http://service1/data", String.class);
String service2Data = restTemplate.getForObject("http://service2/data", String.class);
// 聚合数据
AggregatedResponse response = new AggregatedResponse(service1Data, service2Data);
return response;
}
}
class AggregatedResponse {
private String service1Data;
private String service2Data;
public AggregatedResponse(String service1Data, String service2Data) {
this.service1Data = service1Data;
this.service2Data = service2Data;
}
// getters and setters
}
七 Chained Microservice(微服务链)模式
在某些场景下,服务之间可能有严格的依赖顺序。Chained Microservice 模式表示一个请求通过多个微服务进行处理,每个微服务都执行一部分工作,然后将结果传递给下一个微服务。这种模式适合顺序处理的业务场景。
@RestController
public class ServiceA {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/start")
public String startChain() {
// 第一个微服务的逻辑
String resultA = "Service A processed data";
// 调用下一个微服务 B
String resultB = restTemplate.getForObject("http://serviceB/process?data=" + resultA, String.class);
return resultB;
}
}
在本例中,服务A首先处理一部分数据,然后将处理结果传递给服务B,这种链式调用可以应用于多个服务的顺序处理。
八 Asynchronous Messaging(异步消息传递)模式
异步消息传递允许微服务通过消息队列或事件流进行通信,而无需等待其他服务的响应。这可以极大提高系统的吞吐量和响应速度,尤其适合松耦合、无强实时性的场景。
@EnableBinding(Source.class)
public class AsyncEventProducer {
@Autowired
private MessageChannel output;
public void sendEvent(String data) {
output.send(MessageBuilder.withPayload(data).build());
}
}
@EnableBinding(Sink.class)
public class AsyncEventConsumer {
@StreamListener(Sink.INPUT)
public void handleMessage(String data) {
System.out.println("Received asynchronous message: " + data);
}
}
AsyncEventProducer
通过 Kafka
发布事件,而 AsyncEventConsumer
订阅并处理该事件。微服务之间通过异步消息传递解耦,无需同步等待。
九 Saga(长事务)模式
在微服务中,跨多个服务的数据一致性是一个挑战。Saga 模式是一种处理分布式事务的模式,通过多个服务之间的协调来完成事务操作。如果某个步骤失败,会执行补偿操作以回滚之前的服务状态。Saga 有两种常见的实现方式:**Choreography(编排式)**和 Orchestration(协调式)。
@RestController
public class OrderService {
@Autowired
private RestTemplate restTemplate;
@PostMapping("/createOrder")
public String createOrder(@RequestBody Order order) {
// 1. 创建订单
String orderResult = restTemplate.postForObject("http://inventory-service/reserve", order, String.class);
if (orderResult.equals("success")) {
// 2. 扣减库存成功,执行付款操作
String paymentResult = restTemplate.postForObject("http://payment-service/pay", order, String.class);
if (paymentResult.equals("success")) {
return "Order Created Successfully";
} else {
// 3. 付款失败,执行回滚
restTemplate.postForObject("http://inventory-service/rollback", order, String.class);
return "Order Creation Failed, Inventory Rolled Back";
}
}
return "Order Creation Failed";
}
}
在本例中,如果创建订单成功但付款失败,系统会调用 inventory-service
来回滚之前的库存扣减操作,从而保证系统状态的一致性。
十 Strangler Fig(绞杀者)模式
Strangler Fig 模式用于将一个单体应用逐步重构为微服务架构。新的功能以微服务的方式实现,而旧的功能则保留在原有的单体应用中。随着时间推移,单体应用的功能逐步迁移到微服务中,最终替换整个单体应用。
@SpringBootApplication
public class ApiGatewayApplication {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 新的微服务路由
.route("new_service", r -> r.path("/new-service/**")
.uri("http://new-microservice:8080"))
// 旧的单体应用路由
.route("legacy_app", r -> r.path("/legacy/**")
.uri("http://legacy-app:8081"))
.build();
}
}
在现代大规模企业软件开发中,微服务架构能够帮助开发扩展规模并带来很多长期收益。但是微服务架构并不是随处可用的银弹,如果应用在错误的应用程序类型,微服务架构将弊大于利。希望采用微服务架构的开发团队应该遵循最佳实践,并使用一系列可重用的、久经锤炼的设计模式。