SpringCloud
# SpringCloud
微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。
优点包括:
- 服务拆分:将大型应用分解为多个小的、可管理的服务。
- 远程调用:服务之间通过网络进行通信,通常使用HTTP/HTTPS协议。
- 服务治理:管理和监控服务之间的交互,确保服务的可用性和性能。
- 请求路由:决定请求如何被路由到正确的服务。
- 身份认证:确保只有授权用户可以访问服务。
- 配置管理:管理和更新服务的配置信息。
- 服务保护:防止服务过载或崩溃,例如通过限流和熔断机制。
- 分布式事务:处理跨多个服务的事务一致性问题。
- 异步通信:服务之间通过消息队列等机制进行非阻塞通信。
- 消息可靠性:确保消息在服务间可靠传输。
- 延迟消息:支持定时或延时的消息传递。
- 分布式搜索:在分布式环境中提供高效的搜索能力。
- 倒排索引:一种数据结构,用于快速搜索特定字段值的所有文档。
- 数据聚合:从多个数据源收集和整合数据。
# MybatisPlus
# 2.2.服务拆分原则
服务拆分一定要考虑几个问题:
- 什么时候拆?
- 如何拆?
# 2.2.1.什么时候拆
一般情况下,对于一个初创的项目,首先要做的是验证项目的可行性。因此这一阶段的首要任务是敏捷开发,快速产出生产可用的产品,投入市场做验证。为了达成这一目的,该阶段项目架构往往会比较简单,很多情况下会直接采用单体架构,这样开发成本比较低,可以快速产出结果,一旦发现项目不符合市场,损失较小。
如果这一阶段采用复杂的微服务架构,投入大量的人力和时间成本用于架构设计,最终发现产品不符合市场需求,等于全部做了无用功。
所以,对于大多数小型项目来说,一般是先采用单体架构,随着用户规模扩大、业务复杂后再逐渐拆分为****微服务架构。这样初期成本会比较低,可以快速试错。但是,这么做的问题就在于后期做服务拆分时,可能会遇到很多代码耦合带来的问题,拆分比较困难(前易后难)。
而对于一些大型项目,在立项之初目的就很明确,为了长远考虑,在架构设计时就直接选择微服务架构。虽然前期投入较多,但后期就少了拆分服务的烦恼(前难后易)。
# 2.2.2.怎么拆⭐
之前我们说过,微服务拆分时粒度要小,这其实是拆分的目标。具体可以从两个角度来分析:
- 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。
- 低****耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。
高内聚首先是**单一职责,**但不能说一个微服务就一个接口,而是要保证微服务内部业务的完整性为前提。目标是当我们要修改某个业务时,最好就只修改当前微服务,这样变更的成本更低。
一旦微服务做到了高内聚,那么服务之间的耦合度自然就降低了。
当然,微服务之间不可避免的会有或多或少的业务交互,比如下单时需要查询商品数据。这个时候我们不能在订单服务直接查询商品数据库,否则就导致了数据耦合。而应该由商品服务对应暴露接口,并且一定要保证微服务对外接口的稳定性(即:尽量保证接口外观不变)。虽然出现了服务间调用,但此时无论你如何在商品服务做内部修改,都不会影响到订单微服务,服务间的耦合度就降低了。
明确了拆分目标,接下来就是拆分方式了。我们在做服务拆分时一般有两种方式:
- 纵向拆分
- 横向拆分
所谓纵向拆分,就是按照项目的功能模块来拆分。例如黑马商城中,就有用户管理功能、订单管理功能、购物车功能、商品管理功能、支付功能等。那么按照功能模块将他们拆分为一个个服务,就属于纵向拆分。这种拆分模式可以尽可能提高服务的内聚性。
而横向拆分,是看各个功能模块之间有没有公共的业务部分,如果有将其抽取出来作为通用服务。例如用户登录是需要发送消息通知,记录风控数据,下单时也要发送短信,记录风控数据。因此消息发送、风控数据记录就是通用的业务功能,因此可以将他们分别抽取为公共服务:消息中心服务、风控管理服务。这样可以提高业务的复用性,避免重复开发。同时通用业务一般接口稳定性较强,也不会使服务之间过分耦合。
当然,由于黑马商城并不是一个完整的项目,其中的短信发送、风控管理并没有实现,这里就不再考虑了。而其它的业务按照纵向拆分,可以分为以下几个微服务:
- 用户服务
- 商品服务
- 订单服务
- 购物车服务
- 支付服务
服务拆分后可以使用RestTemplate远程http请求调用
——》
服务是集群的,RestTemplate调用方式是固定的
-》
使用nacos服务注册中心,服务调用者根据服务名可以调用服务注册者在服务注册中心中注册的服务实例,通过负载均衡算法选择出实例进行http请求
->
可以用openFeign将替我们完成上面的服务拉取、负载均衡、发送http请求的所有工作
抽取feign客户端
- 抽取为一个api模块——》适用于一个服务一个模块
- 每个服务模块抽取出一个DTO和Client模块,供其他服务模块依赖引入——适用于一个服务一个project
# 网关
由于每个微服务都有不同的地址或端口,入口不同,相信大家在与前端联调的时候发现了一些问题:
- 请求不同数据时要访问不同的入口,需要维护多个入口地址,麻烦
- 前端无法调用nacos,无法实时更新服务列表
单体架构时我们只需要完成一次用户登录、身份校验,就可以在所有业务中获取到用户信息。而微服务拆分后,每个微服务都独立部署,这就存在一些问题:
- 每个微服务都需要编写登录校验、用户信息获取的功能吗?
- 当微服务之间调用时,该如何传递用户信息?