【微服务】微服务详解、模块化开发详解

发布时间:2024年01月03日

一、微服务简介

微服务架构是一种软件设计和开发的方法,将一个大型的应用程序拆分为一组小而独立的服务。每个服务都运行在自己的进程中,并通过轻量级的通信机制(通常是HTTP API)与其他服务进行通信。这些服务可以独立开发、部署和扩展,因此可以更容易地实现敏捷开发和持续交付。

在微服务架构中,通常一个模块会对应一个微服务,但并不是绝对的规定。微服务的概念强调将一个大型应用程序拆分成一组小而独立的服务,每个服务都运行在自己的进程中,有自己的数据库和业务逻辑。这种拆分的单元通常被称为微服务。

然而,微服务的粒度可以根据特定的需求和设计考虑而变化。有时一个模块可能对应一个微服务,而在其他情况下,一个模块可能被拆分成多个微服务,或者多个模块被合并为一个微服务。
微服务架构的主要特点包括:

  • 模块化性: 应用程序被拆分为小的、自治的服务,每个服务负责特定的业务功能。这使得修改、扩展或替换一个服务变得相对容易。
  • 独立部署: 由于每个服务都是独立的,可以独立地部署、升级和扩展。这意味着一个服务的变更不会对整个应用程序产生影响。
  • 弹性和可伸缩性: 微服务架构允许根据需要独立地扩展每个服务,从而提高系统的弹性和可伸缩性。
  • 技术多样性: 不同的服务可以使用不同的技术栈,因为它们是独立的。这使得团队可以选择最适合其需求的技术。
  • 去中心化数据管理: 每个服务通常有自己的数据库,避免了单一数据库的问题。服务通过API进行通信,而不是直接访问彼此的数据存储。
  • 容错性: 由于每个服务是独立的,系统可以更容易地处理部分故障,而不会导致整个系统的崩溃。

微服务架构适用于复杂的、大规模的应用程序,可以提高开发速度、灵活性和可维护性。然而,它也带来了一些挑战,如服务间的通信、一致性管理和监控等问题需要仔细处理。

二、模块化

1、模块划分维度

  • 业务领域划分:将整个业务领域划分为独立的子领域,每个子领域由一个或多个微服务负责。这种划分方式通常与业务逻辑直接相关,使得每个微服务可以专注于一个特定的业务功能。
  • 团队划分: 将团队的组织结构与微服务划分对应,每个团队负责一个或多个微服务的开发、测试和运维。这种方式有助于提高团队的自治性和独立性。
  • 数据一致性划分: 根据数据的一致性要求,将微服务划分为那些需要强一致性的服务和那些可以采用 eventual consistency
    的服务。这有助于优化系统的性能和扩展性。
  • 技术栈划分: 将微服务划分为使用不同技术栈的服务,以满足特定的技术需求。例如,一个微服务可以使用Java,而另一个使用Node.js。
  • API 界面划分: 根据应用程序的外部接口,将微服务划分为负责不同 API 端点或服务的服务。这种划分方式有助于提高系统的灵活性和可扩展性。
  • 安全隔离划分: 根据安全需求,将微服务划分为具有不同安全级别的服务。一些服务可能需要更严格的安全措施,而其他服务可能可以采用更灵活的安全策略。
  • 流程划分: 将微服务划分为负责整个业务流程的服务。每个服务可以代表业务流程中的一个阶段,从而形成一个端到端的业务处理链。

在实际应用中,这些划分维度可能会相互交织,根据具体的业务需求和系统架构来选择最合适的划分方式。微服务的划分应该是一个灵活的过程,需要不断调整以适应不断变化的需求。

2、模块化父子模块的结构形式

微服务架构中可以存在多层的模块化结构,其中一个父模块包含子模块,而子模块本身也可以再包含子模块。这种层次化的结构有时被称为嵌套微服务或子服务。

举例来说,一个微服务应用可以被划分为多个父模块,每个父模块负责一个特定的领域或业务功能。然后,每个父模块下可能包含多个子模块,这些子模块可以进一步划分为更小的子模块。这样的嵌套结构可以根据业务需求和系统复杂性进行灵活设计。

例如:

父模块 A:
	子模块 A1
		子模块 A1.1
		子模块 A1.2
	子模块 A2
	
父模块 B:
	子模块 B1
		子模块 B1.1
		子模块 B1.2
	子模块 B2

在这个例子中,父模块 A 和 B 分别代表不同的领域或业务功能,而每个父模块下都有一层或多层的子模块。这种嵌套结构可以根据业务的复杂性、团队的组织结构以及系统的需求进行设计。

重要的是,无论嵌套层次如何,每个模块(父模块或子模块)都应该遵循微服务架构的原则,即模块间要有清晰的接口定义,模块间通信通过轻量级的机制(例如 API 调用、消息队列等)进行,每个模块都可以独立开发、部署和扩展。这样的结构有助于提高系统的可维护性、灵活性和可扩展性。

三、模块间的通信

在一个系统中,不同模块之间的通信是至关重要的,尤其在微服务架构中。模块间的通信可以通过多种方式实现,具体的选择取决于系统的设计需求、性能要求和架构决策。以下是一些常见的模块间通信方式:

1、HTTP/RESTful API:

使用HTTP或RESTful API是一种常见的模块间通信方式。每个微服务可以通过HTTP请求和响应进行通信,利用GetMapping或者PostMapping定义清晰的API接口,实现松耦合的通信。

假设有两个微服务,一个是用户服务,另一个是订单服务。用户服务提供了获取用户信息的接口,而订单服务需要获取用户信息。

  • 用户服务的 RESTful API:

    UserController {
    
        @GetMapping("/{userId}")
        public ResponseEntity<User> getUserById(@PathVariable Long userId) {
            // 根据用户ID从数据库中获取用户信息
            User user = userRepository.findById(userId).orElse(null);
            if (user != null) {
                return ResponseEntity.ok(user);
            } else {
                return ResponseEntity.notFound().build();
            }
        } } ```
    
  • 订单服务调用用户服务的示例:

    
        private final RestTemplate restTemplate;
    
        @Autowired
        public OrderService(RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
        }
    
        public User getUserById(Long userId) {
            // 调用用户服务的 RESTful API 获取用户信息
            String userApiUrl = "http://user-service/api/users/" + userId;
            return restTemplate.getForObject(userApiUrl, User.class);
        } } ```
    
    

2、消息队列:

模块间的通信可以通过消息队列实现异步消息传递。一种模块发布消息,而其他模块订阅并处理这些消息。消息队列提供了解耦的方式,适用于实现松散耦合和异步通信。

假设有一个微服务负责处理库存更新,而另一个微服务负责处理订单创建。订单创建后,需要通知库存服务更新库存。

  • 订单服务发送消息到消息队列:

    
        private final RabbitTemplate rabbitTemplate;
    
        @Autowired
        public OrderService(RabbitTemplate rabbitTemplate) {
            this.rabbitTemplate = rabbitTemplate;
        }
    
        public void createOrder(Order order) {
            // 订单创建逻辑...
    
            // 发送消息到消息队列
            rabbitTemplate.convertAndSend("order-exchange", "order.created", order);
        } } ```
    
  • 库存服务监听消息队列:

    
        @RabbitListener(queues = "order.created.queue")
        public void handleOrderCreated(Order order) {
            // 处理订单创建消息,更新库存
            // ...
        } } ```
    
    

这是一个简化的例子,实际场景中,需要更多的配置和错误处理机制。

  • RPC(远程过程调用):

    使用RPC,一个模块可以调用另一个模块提供的远程服务,就像调用本地函数一样。通常有像 gRPC、Apache Thrift 等框架支持的二进制协议,也有像 JSON-RPC、XML-RPC 这样基于文本的协议。

  • WebSocket:

    WebSocket提供了全双工通信的能力,适用于实时应用。模块可以通过WebSocket建立持久连接,实现实时的双向通信。

  • 数据库和共享存储:

    模块之间可以通过数据库或共享存储进行数据的共享。一个模块写入数据,而其他模块读取这些数据。这种通信方式通常涉及对数据一致性和并发性的处理。

  • 事件驱动架构:

    模块可以通过发布-订阅模式进行通信,其中一个模块发布事件,而其他模块订阅并对这些事件进行响应。这种方式有助于实现解耦合的异步通信。

  • GraphQL:

    GraphQL 是一种用于 API 的查询语言,允许客户端指定其需要的数据结构和格式。模块可以使用GraphQL来定义和查询API,使得通信更加灵活。

  • 内存共享:

    在同一台服务器上运行的模块之间,可以使用内存共享来进行通信。这可以通过共享内存区域、缓存或其他内存数据结构来实现。

每种通信方式都有其优势和适用场景,具体的选择取决于系统的需求、架构设计和开发团队的偏好。通常,为了实现松耦合、高性能和可扩展性,开发者可能会选择多种通信方式的组合。

文章来源:https://blog.csdn.net/weixin_45188218/article/details/135362045
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。