微服务的认识与拆分

微服务架构通过将应用分解为一组小的、独立的服务来实现,每个服务围绕特定业务功能构建,并能独立部署与扩展。这种架构增强了开发灵活性、提高了系统的可维护性和扩展性,使得团队可以更快地响应变化和市场需求。

目录

认识微服务

单体架构

微服务架构

微服务拆分

服务拆分原则

拆分时机

拆分细则

微服务工程结构

服务拆分实现

服务调用


认识微服务

单体架构

单体架构:顾名思义,整个项目中所有功能模块都在一个工程中开发;项目部署时需要对所有模块一起编译、打包;项目的架构设计、开发模式都非常简单。

适用场景;当项目规模较小时,这种模式上手快,部署、运维也都很方便,因此早期很多小型项目都采用这种模式。

项目的业务规模越来越大,团队开发人员也不断增加,单体架构就呈现出越来越多的问题:

  • 团队协作成本高:试想一下,你们团队数十个人同时协作开发同一个项目,由于所有模块都在一个项目中,不同模块的代码之间物理边界越来越模糊。最终要把功能合并到一个分支,你绝对会陷入到解决冲突的泥潭之中。

  • 系统发布效率低:任何模块变更都需要发布整个系统,而系统发布过程中需要多个模块之间制约较多,需要对比各种文件,任何一处出现问题都会导致发布失败,发布耗时。

  • 系统可用性差:单体架构各个功能模块是作为一个服务部署,相互之间会互相影响,一些热点功能会耗尽系统资源,导致其它服务低可用。

此时如果我们对系统做水平扩展,增加更多机器,资源还是会被这样的热点接口占用,从而影响到其它接口,并不能从根本上解决问题。这也就是单体架构的扩展性差的一个原因。

微服务架构

为了解决单体架构因为带来的问题,于是微服务出现了。

微服务架构,首先是服务化,就是将单体架构中的功能模块从单体应用中拆分出来,独立部署为多个服务。同时要满足下面的一些特点:

  • 单一职责:一个微服务负责一部分业务功能,并且其核心数据不依赖于其它模块。

  • 团队自治:每个微服务都有自己独立的开发、测试、发布、运维人员,团队人员规模不超过10人(2张披萨能喂饱)

  • 服务自治:每个微服务都独立打包部署,访问自己独立的数据库。并且要做好服务隔离,避免对其它服务产生影响

问题解决:

问题一:由于服务拆分,每个服务代码量大大减少,参与开发的后台人员在1~3名,协作成本大大降低

问题二:每个服务都是独立部署,当有某个服务有代码变更时,只需要打包部署该服务即可

问题三:每个服务独立部署,并且做好服务隔离,使用自己的服务器资源,不会影响到其它服务

当然,对于Java领域开发者来说,SpringCloud框架可以说是目前最全面的微服务组件的集合。

微服务拆分

服务拆分原则

拆分时机

在项目初期,尤其是初创项目,通常优先考虑敏捷开发以快速产出可投入市场的最小可行产品(MVP),以便尽早验证项目的可行性。此时,采用简单的单体架构较为常见,因其开发成本低、部署快速,即便项目最终不被市场接受,损失也相对较小。随着用户量增长和业务复杂度提升,再逐步向微服务架构迁移,尽管这可能会导致后期因代码耦合面临拆分难题。

相反,对于从立项就目标明确的大型项目 ,考虑到长期发展和扩展性,初期即选择复杂的微服务架构进行设计。这种方式虽然前期需要更多的资源投入,但有利于后续的维护与扩展,避免了日后服务拆分的困扰。简而言之:

初创小项目:先用单体架构快速上线测试市场反应,之后视情况转向微服务(前易后难)。

大型明确项目:直接采用微服务架构规划长远发展,减少后期重构麻烦(前难后易)。

拆分细则

拆分目标角度:

高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。

耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。

拆分方式角度:

纵向拆分:依据项目功能模块进行拆分。例如,在一个电商应用中,可以将用户管理、订单管理、购物车、商品管理和支付等功能各自独立为单独的服务。这种方式提高了每个服务的内聚性,使得各服务专注于特定业务领域。

横向拆分:识别并提取各个功能模块中的共通业务逻辑作为通用服务。比如,无论是用户登录还是下单过程,都涉及到发送消息通知和记录风控数据的操作。这些共用的功能可以被抽取出来,形成独立的消息中心服务和风控管理服务。这样做不仅提高了代码复用性,减少了重复开发工作,而且由于接口相对稳定,不会造成服务间的过度耦合。

微服务工程结构

一般微服务项目有两种不同的工程结构:

完全解耦

  • 描述:每个微服务是一个独立工程,可使用不同语言开发。
  • 优点:服务间耦合度低。
  • 缺点:各自独立仓库,管理复杂。

Maven聚合

  • 描述:整个项目作为一个Project,各微服务为Module。
  • 优点:代码集中,便于管理和运维。
  • 缺点:服务间存在耦合,编译时间较长。

服务拆分实现

按照Maven聚合实现拆分对于小型项目更为合适。

针对于已经完成开发的项目,我们拆分一般按照以下步骤:

1.对于拆分服务的精确划分,应尽量符合服务拆分原则

2.新建对于模块,并且引入依赖,配置application.yaml等配置文件

3.正确引入实体类,controller,service,mapper等业务代码

事实上,往往服务内都会需要进行,对于服务的调用,我们该如何跨服务调用?

服务调用

RestTemplate

Spring给我们提供了一个RestTemplate的API,可以方便的实现Http请求的发送。

先将RestTemplate注册为一个Bean

java 复制代码
@Configuration
public class RemoteCallConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

利用RestTemplate发送http请求

java 复制代码
        ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
                "http://localhost:8081/items?ids={ids}",// 请求URL,包含占位符{ids}
                HttpMethod.GET,// 使用GET方法
                null,// 不使用请求体或请求头
                new ParameterizedTypeReference<List<ItemDTO>>() {}, // 指定响应类型为List<ItemDTO>
                Map.of("ids", CollUtil.join(itemIds, ","))// 替换URL中的{ids}为逗号分隔的itemIds字符串
        );
        // 2.2.解析响应
        if(!response.getStatusCode().is2xxSuccessful()){
            // 查询失败,直接结束
            return;
        }
        List<ItemDTO> items = response.getBody();

测试完毕:实现服务之间进行远程调用

相关推荐
海鸥811 小时前
查看k8s集群的资源使用情况
云原生·容器·kubernetes
云上艺旅1 小时前
K8S学习之基础十八:k8s的灰度发布和金丝雀部署
学习·云原生·容器·kubernetes
-代号95274 小时前
【RocketMQ】二、架构与核心概念
架构·rocketmq·java-rocketmq
ChinaRainbowSea5 小时前
Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案
java·linux·运维·服务器·docker·架构
技术流Garen6 小时前
MCU与SFU:实时音视频通信架构的对比
架构·实时音视频
云上艺旅7 小时前
K8S学习之基础十五:k8s中Deployment扩容缩容
学习·docker·云原生·kubernetes·k8s
小华同学ai8 小时前
2K star!三分钟搭建企业级后台系统,这款开源Java框架绝了!
后端·架构·github
Lei活在当下9 小时前
【Android架构底层逻辑拆解】Google官方项目NowInAndroid研究(2)数据层的设计和实现之model与database
架构
福鸦9 小时前
C++ STL深度解析:现代编程的瑞士军刀
开发语言·c++·算法·安全·架构
DemonAvenger9 小时前
深入Go并发编程:Goroutine性能调优与实战技巧全解析
设计模式·架构·go