黑马商城微服务-上

微服务

微服务(Microservices)是一种分布式架构风格,它将一个大型应用程序拆分为多个小型、独立的服务,每个服务专注于完成特定的业务功能,并通过定义良好的接口(如 API)进行通信。这种架构的核心目标是提高系统的灵活性、可维护性和可扩展性。


微服务的核心特点

  1. 小型、独立、松耦合

    • 每个微服务是一个独立的进程或组件,拥有自己的代码库、数据库和配置。
    • 服务之间通过轻量级通信机制(如 REST API、gRPC、消息队列)交互,彼此不直接依赖。
  2. 独立部署和运行

    • 每个微服务可以独立开发、测试、部署和扩展,无需重新部署整个应用程序。
    • 例如:支付服务升级时,不影响订单服务或用户服务。
  3. 技术栈灵活性

    • 不同微服务可以使用不同的编程语言、框架或数据库(即“多语言编程”)。
    • 例如:用户服务用 Java,支付服务用 Python,库存服务用 Go。
  4. 有界上下文和业务能力

    • 每个微服务围绕一个明确的业务功能设计(如用户管理、订单处理、支付),并遵循领域驱动设计(DDD)的“有界上下文”原则。
  5. 去中心化

    • 数据存储去中心化:每个服务管理自己的数据库,避免共享数据库的瓶颈。
    • 治理去中心化:团队可以自主选择工具和技术,提升开发效率。

微服务的典型应用场景

  • 复杂业务需求:当系统功能复杂且需要频繁迭代时(如电商、金融系统)。
  • 多团队协作:不同团队可以并行开发和维护独立的微服务。
  • 高可扩展性需求:某些功能(如秒杀活动)需要独立扩展,而其他模块无需扩容。
  • 技术异构:需要结合不同技术栈(如遗留系统与新技术共存)。

微服务的优势

  1. 敏捷开发与快速交付

    • 独立部署允许团队快速迭代功能,缩短发布周期。
    • 例如:修复一个微服务的 bug 不需要重新部署整个应用。
  2. 高可扩展性

    • 按需扩展特定服务(如双十一期间扩容支付服务),节省资源成本。
  3. 故障隔离

    • 单个服务故障不会导致整个系统崩溃(通过断路器、熔断机制等实现)。
  4. 技术灵活性

    • 团队可根据业务需求选择最适合的技术栈,避免“一刀切”的技术约束。
  5. 持续集成/持续交付(CI/CD)支持

    • 微服务天然适合自动化部署流程,便于实现 DevOps 实践。

微服务的挑战

  1. 分布式系统复杂性

    • 需要处理服务发现、负载均衡、分布式事务、日志聚合等问题。
    • 例如:跨服务调用时如何保证一致性(可采用 Saga 模式或事件溯源)。
  2. 运维成本增加

    • 服务数量多,部署、监控和调试难度上升(需借助 Kubernetes、Service Mesh 等工具)。
  3. 网络延迟与可靠性

    • 服务间通信依赖网络,可能引入延迟和故障(需通过重试、超时机制优化)。
  4. 接口管理

    • 不同版本的服务接口需要兼容性设计(如 OpenAPI 规范)。

微服务 vs 单体架构

特性 单体架构 微服务架构
部署方式 整体部署(一次发布整个应用) 独立部署(每个服务单独发布)
技术栈 通常使用单一技术栈 支持多语言、多框架
可扩展性 只能整体扩展 按需扩展特定服务
故障影响范围 单点故障可能导致整个系统崩溃 故障隔离,影响局部服务
开发团队协作 单一团队维护整个代码库 多个团队并行开发独立服务
适用场景 小型项目或简单业务 复杂业务、高并发场景

微服务的实现技术

  • 框架与工具
    • Spring Cloud(Java 生态,提供服务注册、配置管理、网关等功能)
    • Dubbo(高性能 RPC 框架)
    • Service Mesh(如 Istio、Linkerd,用于服务治理)
  • 基础设施
    • 容器化(Docker、Kubernetes)
    • API 网关(如 Kong、Zuul)
    • 服务注册与发现(Consul、Eureka)

总结

微服务架构是云原生时代的核心实践,适合需要高灵活性、可扩展性和快速迭代的复杂系统。然而,它并非万能方案,需权衡业务需求与团队能力。对于小型项目或初期阶段,单体架构可能更简单高效;而当业务规模扩大、团队分工细化时,微服务则能显著提升系统的可靠性和开发效率。

认识微服务

单体架构(monolithic structure):顾名思义,整个项目中所有功能模块都在一个工程中开发;项目部署时需要对所有模块一起编译、打包;项目的架构设计、开发模式都非常简单。
当项目规模较小时,这种模式上手快,部署、运维也都很方便,因此早期很多小型项目都采用这种模式。

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

  • 团队协作成本高:试想一下,你们团队数十个人同时协作开发同一个项目,由于所有模块都在一个项目中,不同模块的代码之间物理边界越来越模糊。最终要把功能合并到一个分支,你绝对会陷入到解决冲突的泥潭之中。
  • 系统发布效率低:任何模块变更都需要发布整个系统,而系统发布过程中需要多个模块之间制约较多,需要对比各种文件,任何一处出现问题都会导致发布失败,往往一次发布需要数十分钟甚至数小时。
  • 系统可用性差:单体架构各个功能模块是作为一个服务部署,相互之间会互相影响,一些热点功能会耗尽系统资源,导致其它服务低可用。

在上述问题中,前两点相信大家在实战过程中应该深有体会。对于第三点系统可用性问题,很多同学可能感触不深。接下来我们就通过黑马商城这个项目,给大家做一个简单演示。
首先,我们修改hm-service模块下的com.hmall.controller.HelloController中的hello方法,模拟方法执行时的耗时:
在这里插入图片描述
接下来,启动项目,目前有两个接口是无需登录即可访问的:

  • http://localhost:8080/hi
  • http://localhost:8080/search/list
    经过测试,目前/search/list 是比较正常的,访问耗时在30毫秒左右。

接下来,我们假设/hi这个接口是一个并发较高的热点接口,我们通过Jemeter来模拟500个用户不停访问。在课前资料中已经提供了Jemeter的测试脚本:
在这里插入图片描述
这个脚本会开启500个线程并发请求http://localhost/hi这个接口。由于该接口存在执行耗时(500毫秒),这就服务端导致每秒能处理的请求数量有限,最终会有越来越多请求积压,直至Tomcat资源耗尽。这样,其它本来正常的接口(例如/search/list)也都会被拖慢,甚至因超时而无法访问了。
我们测试一下,启动测试脚本,然后在浏览器访问http://localhost:8080/search/list这个接口,会发现响应速度非常慢:
在这里插入图片描述
如果进一步提高/hi这个接口的并发,最终会发现/search/list接口的请求响应速度会越来越慢。

可见,单体架构的可用性是比较差的,功能之间相互影响比较大。
当然,有同学会说我们可以做水平扩展。
此时如果我们对系统做水平扩展,增加更多机器,资源还是会被这样的热点接口占用,从而影响到其它接口,并不能从根本上解决问题。这也就是单体架构的扩展性差的一个原因。

微服务

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

  • 单一职责:一个微服务负责一部分业务功能,并且其核心数据不依赖于其它模块。
  • 团队自治:每个微服务都有自己独立的开发、测试、发布、运维人员,团队人员规模不超过10人(2张披萨能喂饱)
  • 服务自治:每个微服务都独立打包部署,访问自己独立的数据库。并且要做好服务隔离,避免对其它服务产生影响

例如,黑马商城项目,我们就可以把商品、用户、购物车、交易等模块拆分,交给不同的团队去开发,并独立部署:
在这里插入图片描述
微服务架构解决了单体架构存在的问题,特别适合大型互联网项目的开发,因此被各大互联网公司普遍采用。大家以前可能听说过分布式架构,分布式就是服务拆分的过程,其实微服务架构正式分布式架构的一种最佳实践的方案。

当然,微服务架构虽然能解决单体架构的各种问题,但在拆分的过程中,还会面临很多其它问题。比如:

  • 如果出现跨服务的业务该如何处理?
  • 页面请求到底该访问哪个服务?
  • 如何实现各个服务之间的服务隔离?

目前SpringCloud最新版本为2022.0.x版本,对应的SpringBoot版本为3.x版本,但它们全部依赖于JDK17,目前在企业中使用相对较少。

推荐使用次新版本:Spring Cloud 2021.0.x以及Spring Boot 2.7.x版本。

另外,Alibaba的微服务产品SpringCloudAlibaba目前也成为了SpringCloud组件中的一员,我们课堂中也会使用其中的部分组件。

在我们的父工程hmall中已经配置了SpringCloud以及SpringCloudAlibaba的依赖:

在这里插入图片描述

服务拆分

熟悉项目
在这里插入图片描述
记得修改数据库连接信息
在这里插入图片描述
配置启动项激活的是local环境:
在这里插入图片描述

登录

登录过程的时序图
在这里插入图片描述
登录接口在com.hmall.controller.UserController中的login方法。

搜索商品

在首页搜索框输入关键字,点击搜索即可进入搜索列表页面:
在这里插入图片描述
该页面会调用接口:/search/list,对应的服务端入口在com.hmall.controller.SearchController中的search方法.

购物车

在搜索到的商品列表中,点击按钮加入购物车,即可将商品加入购物车:
在这里插入图片描述
加入购物车后可查询购物车列表信息
在这里插入图片描述
同时这里还可以对购物车实现修改、删除等操作。
相关功能全部在com.hmall.controller.CartController中。

其中,查询购物车列表时,由于要判断商品最新的价格和状态,所以还需要查询商品信息,业务流程如下:
在这里插入图片描述

下单

在购物车页面点击结算按钮,会进入订单结算页面:
在这里插入图片描述
点击提交订单,会提交请求到服务端,服务端做3件事情:

  • 创建一个新的订单
  • 扣减商品库存
  • 清理购物车中商品
    业务入口在com.hmall.controller.OrderController中的createOrder方法。

支付

下单完成后会跳转到支付页面,目前只支持余额支付:
在这里插入图片描述
在选择余额支付这种方式后,会发起请求到服务端,服务端会立刻创建一个支付流水单,并返回支付流水单号到前端。
当用户输入用户密码,然后点击确认支付时,页面会发送请求到服务端,而服务端会做几件事情:

  • 校验用户密码
  • 扣减余额
  • 修改支付流水状态
  • 修改交易订单状态
    请求入口在com.hmall.controller.PayController中。

服务拆分原则

服务拆分一定要考虑几个问题:

  • 什么时候拆?
  • 如何拆?

什么时候拆

一般情况下,对于一个初创的项目,首先要做的是验证项目的可行性。因此这一阶段的首要任务是敏捷开发,快速产出生产可用的产品,投入市场做验证。为了达成这一目的,该阶段项目架构往往会比较简单,很多情况下会直接采用单体架构,这样开发成本比较低,可以快速产出结果,一旦发现项目不符合市场,损失较小。
如果这一阶段采用复杂的微服务架构,投入大量的人力和时间成本用于架构设计,最终发现产品不符合市场需求,等于全部做了无用功。
所以,对于大多数小型项目来说,一般是先采用单体架构,随着用户规模扩大、业务复杂后再逐渐拆分为微服务架构。这样初期成本会比较低,可以快速试错。但是,这么做的问题就在于后期做服务拆分时,可能会遇到很多代码耦合带来的问题,拆分比较困难(前易后难)。
而对于一些大型项目,在立项之初目的就很明确,为了长远考虑,在架构设计时就直接选择微服务架构。虽然前期投入较多,但后期就少了拆分服务的烦恼(前难后易)。

怎么拆

之前我们说过,微服务拆分时粒度要小,这其实是拆分的目标。具体可以从两个角度来分析:

  • 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。
  • 低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。

高内聚首先是单一职责,但不能说一个微服务就一个接口,而是要保证微服务内部业务的完整性为前提。目标是当我们要修改某个业务时,最好就只修改当前微服务,这样变更的成本更低。
一旦微服务做到了高内聚,那么服务之间的耦合度自然就降低了。
当然,微服务之间不可避免的会有或多或少的业务交互,比如下单时需要查询商品数据。这个时候我们不能在订单服务直接查询商品数据库,否则就导致了数据耦合。而应该由商品服务对应暴露接口,并且一定要保证微服务对外接口的稳定性(即:尽量保证接口外观不变)。虽然出现了服务间调用,但此时无论你如何在商品服务做内部修改,都不会影响到订单微服务,服务间的耦合度就降低了。

明确了拆分目标,接下来就是拆分方式了。我们在做服务拆分时一般有两种方式:

  • 纵向拆分
  • 横向拆分

所谓纵向拆分,就是按照项目的功能模块来拆分。例如黑马商城中,就有用户管理功能、订单管理功能、购物车功能、商品管理功能、支付功能等。那么按照功能模块将他们拆分为一个个服务,就属于纵向拆分。这种拆分模式可以尽可能提高服务的内聚性。

横向拆分,是看各个功能模块之间有没有公共的业务部分,如果有将其抽取出来作为通用服务。例如用户登录是需要发送消息通知,记录风控数据,下单时也要发送短信,记录风控数据。因此消息发送、风控数据记录就是通用的业务功能,因此可以将他们分别抽取为公共服务:消息中心服务、风控管理服务。这样可以提高业务的复用性,避免重复开发。同时通用业务一般接口稳定性较强,也不会使服务之间过分耦合。

当然,由于黑马商城并不是一个完整的项目,其中的短信发送、风控管理并没有实现,这里就不再考虑了。而其它的业务按照纵向拆分,可以分为以下几个微服务:

  • 用户服务
  • 商品服务
  • 订单服务
  • 购物车服务
  • 支付服务

拆分购物车、商品服务

接下来,我们先把商品管理功能、购物车功能抽取为两个独立服务。
一般微服务项目有两种不同的工程结构:

  • 完全解耦:每一个微服务都创建为一个独立的工程,甚至可以使用不同的开发语言来开发,项目完全解耦。
    • 优点:服务之间耦合度低
    • 缺点:每个项目都有自己的独立仓库,管理起来比较麻烦
  • Maven聚合:整个项目为一个Project,然后每个微服务是其中的一个Module
    • 优点:项目代码集中,管理和运维方便(授课也方便)
    • 缺点:服务之间耦合,编译时间较长

在hmall父工程之中,我已经提前定义了SpringBoot、SpringCloud的依赖版本,所以为了方便期间,我们直接在这个项目中创建微服务module.

商品服务

创建module,选择JDK11版本,商品模块,我们起名为item-service,引入基本依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>hmall</artifactId>
        <groupId>com.heima</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>item-service</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <!--common-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframew
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值