微服务01

单体项目:所有的业务功能集中在一个项目中开发,打包成一个包部署

优点:架构简单,部署成本低

缺点:团队协作成本高,系统发布效率低,系统可用性差

合适开发功能相对简单,规模较小的项目。不适合复杂的项目

微服务

微服务架构,是服务化思想指导下的一套最佳实践架构方案。服务化,就是把单体架构的功能模块拆分成多个独立的项目。

拆分要求:粒度小,团队自治(开发独立),服务自治(打包,编译独立)

缺点:运维难度高,

SpringCloud

SpringCloud框架是目前Java领域较为全面的微服务组件集合。依托于SpringBoot的自动装配能力,大大降低了其项目搭建、组件使用的成本。

Spring Cloud

微服务拆分
微服务拆分原则

一般情况下,对于一个初创的项目,首先要做的是验证项目的可行性。因此这一阶段的首要任务是敏捷开发,快速产出生产可用的产品,投入市场做验证。为了达成这一目的,该阶段项目架构往往会比较简单,很多情况下会直接采用单体架构,这样开发成本比较低,可以快速产出结果,一旦发现项目不符合市场,损失较小。

所以,对于大多数小型项目来说,一般是先采用单体架构 ,随着用户规模扩大、业务复杂后再逐渐拆分为 微服务架构。这样初期成本会比较低,可以快速试错。但是,这么做的问题就在于后期做服务拆分时,可能会遇到很多代码耦合带来的问题,拆分比较困难。

而对于一些大型项目,在立项之初目的就很明确,为了长远考虑,在架构设计时就直接选择微服务架构。虽然前期投入较多,但后期就少了拆分服务的烦恼。

拆分目标:

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

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

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

并且一定要保证微服务对外接口的稳定性(即:尽量保证接口外观不变)。虽然出现了服务间调用,但此时无论你如何在一个服务做内部修改,都不会影响到其他微服务,服务间的耦合度就降低了。

拆分方式:

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

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

工程结构

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

  • 完全解耦:每一个微服务都创建为一个独立的工程,甚至可以使用不同的开发语言来开发,项目完全解耦。

    • 优点:服务之间耦合度低

    • 缺点:每个项目都有自己的独立仓库,管理起来比较麻烦

  • Maven聚合:整个项目为一个Project,然后每个微服务是其中的一个Module

    • 优点:项目代码集中,管理和运维方便

    • 缺点:服务之间耦合,编译时间较长

远程调用

微服务进行拆分后,服务与服务之间的代码和数据库都物理分隔开了,为解决服务与服务之间的数据查询我们可以在java程序之间进行http请求。

RestTemplate

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

其中提供了大量的方法,方便我们发送Http请求,例如:

1.先将RestTemplate注册为一个Bean:

@Configuration

public class RemoteCallConfig {

@Bean

public RestTemplate restTemplate() {

return new RestTemplate();

}

}

2.发送远程调用

服务治理

通过Http请求实现的跨微服务的远程调用,这个方式存在一些问题。

假如某个微服务被调用较多,为了应对更高的并发,我们进行了多实例部署

此时,每个微服务的实例其IP或端口不同,问题来了:

  • 这么多实例,其他微服务如何知道每一个实例的地址?

  • http请求要写url地址,其他服务到底该调用哪个实例呢?

  • 如果在运行过程中,某一个实例宕机,其他服务依然在调用该怎么办?

  • 如果并发太高,临时多部署了N台实例,其他服务如何知道新实例的地址?

为了解决上述问题,就必须引入注册中心的概念了。

注册中心

在微服务远程调用的过程中,包括两个角色:

服务提供者:提供接口供其它微服务访问

服务消费者:调用其它微服务提供的接口

在大型微服务项目中,服务提供者的数量会非常多,为了管理这些服务就引入了注册中心的概念。注册中心、服务提供者、服务消费者三者间关系如下:

流程如下:

  • 服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心

  • 调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)

  • 调用者自己对实例列表负载均衡,挑选一个实例

  • 调用者向该实例发起远程调用

当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?

  • 服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)

  • 当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除

  • 当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表

  • 当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表

服务注册

(需要搭建nacos注册中心,按名称管理服务实例)

启动多个实例,打开nacos注册中心页面可以发现服务注册成功

服务发现

服务的消费者要去nacos订阅服务,这个过程就是服务发现,步骤如下:

1.引入依赖

复制代码
<dependency>
<groupId>com.alibaba.cloud</groupId> 
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> 
</dependency>

2.配置Nacos地址

复制代码
spring: 
        cloud: 
                nacos: 
                        server-addr: xxx.xxx.xxx.xxx:8848

3.发现并调用服务

注册中心有多个实例的信息,而真正发起调用时只需要知道一个实例的地址。

服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:

1.随机

2.轮询

3.IP的hash

4.最近最少访问

另外,服务发现需要用到一个工具DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:

OpenFeign

OpenFeigin是一个声明式的http客户端,是作用就是基于SpringMVC常见注解来实现http请求的发送

其实远程调用的关键点就在于四个:

1.请求方式

2.请求路径

3.请求参数

4.返回值类型

所以,OpenFeign就利用SpringMVC的相关注解来声明上述4个参数,然后基于动态代理帮我们生成远程调用的代码,而无需我们手动再编写。

1.引入依赖

<!--openFeign--><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>

<!--负载均衡器--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>

2.在启动项中加入注解@EnableFeignClients启用OpenFeign

3.编写OpenFeign客户端

4.使用OpenFeign客户端,实现远程调用

feign替我们完成了服务拉取、负载均衡、发送http请求的所有工作

连接池

使用其他http框架

重启服务,连接池就生效了。

最佳实践

方法一 服务暴露的接口客户端由对应项目组编写 项目结构复杂

方法二 耦合度高 横向拆分

日志

在api模块下新建一个配置类,定义Feign的日志级别:

接下来,要让日志级别生效,还需要配置这个类。有两种方式:

局部生效:在某个FeignClient中配置,只对当前FeignClient生效

@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)

全局生效:在@EnableFeignClients中配置,针对所有FeignClient生效。

@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)

相关推荐
虾米Life27 分钟前
基于微服务脚手架的视频点播系统 (仿B站) [客户端] -1
c++·qt·微服务·架构
悠闲蜗牛�28 分钟前
智能时代技术融合之道:大模型、微服务与数据安全的系统化实践
微服务·云原生·架构
胡耀超35 分钟前
通往AGI的模块化路径:一个可能的技术架构(同时解答微调与RAG之争)
人工智能·python·ai·架构·大模型·微调·agi
人生苦短1282 小时前
Kubernetes(k8s)
云原生·容器·kubernetes
凤凰战士芭比Q12 小时前
LNMP环境部署 KodBox私有云盘
linux·架构
小猪咪piggy13 小时前
【微服务】(4) 负载均衡
微服务·云原生·架构
短视频矩阵源码定制14 小时前
矩阵系统哪个好?2025年全方位选型指南与品牌深度解析
java·人工智能·矩阵·架构·aigc
xyhshen15 小时前
记录一次K8S跨命名空间访问 xxx.xxx.svc.cluster.local 类似内部服务不通的问题
云原生·容器·kubernetes
海鸥8115 小时前
在k8s中部署seaweedfs,上传文件到seaweedfs方法
云原生·容器·kubernetes
DARLING Zero two♡15 小时前
云原生基石的试金石:基于 openEuler 部署 Docker 与 Nginx 的全景实录
nginx·docker·云原生