【面试】你知道微服务架构有哪些设计模式吗

        微服务架构是一种软件开发方法,将一个应用拆分为多个小型、独立的服务,每个服务只负责一个特定的功能。这些服务可以独立部署、扩展和维护,通常通过轻量级通信机制(如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();
    }
}

        在现代大规模企业软件开发中,微服务架构能够帮助开发扩展规模并带来很多长期收益。但是微服务架构并不是随处可用的银弹,如果应用在错误的应用程序类型,微服务架构将弊大于利。希望采用微服务架构的开发团队应该遵循最佳实践,并使用一系列可重用的、久经锤炼的设计模式。 

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值