SpringCloud实战

环境准备:

1. 一台虚拟机,部署好centos7操作系统、安装好docker

2. 使用docker安装mysql数据库且启动mysql容器

3. IDEA配置的JDK版本是11

4. 前端代码启动Nginx

一、单体架构和微服务的区别?

1. 单体架构

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

优点:

架构简单、部署成本低

缺点:

  • 团队协作成本高(多人在一个项目上提交代码容易造成很多的代码冲突,每天解决代码需要很久)
  • 系统发布效率低(当代码体量过大时,重新发布需要耗时长)
  • 系统可用性差(假如项目中有某些并发量很大的功能,还有一些访问量不大但是很重要的功能,例如:付款。服务器资源是有限的,一些功能占用了大量的资源,会影响别的功能的正常运转)使用apache-jmeter模拟测试

总结: 单体架构适合开发功能相对简单,规模较小的项目。

2. 微服务

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

3. SpringCloud 

SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud。 SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:

二、微服务拆分

1. 服务拆分原则

1.1 什么时候拆分?

创业型项目:先采用单体架构,快速开发,快速试错。随着规模扩大,逐渐拆分。

确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免后续拆分的麻烦。

1.2 怎么拆分

拆分目标来说,要做到:

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

拆分方式来说,一般包含两种方式:

  • 纵向拆分:按照业务模块来拆分
  • 横向拆分:抽取公共服务,提高复用性

2. 服务拆分

工程结构有两种:

  • 独立Project
  • Maven聚合(每个module以后是要分别打包部署的)

3. 远程调用

当存在业务耦合的情况时,比如购物车模块需要调用商品模块的接口服务,但又不在一个模块中,这个时候就需要了解远程调用了!

思考一下:前端访问后端,不也是两个服务之间的交互,是怎么实现的呢?

从控制台可以看到,前后端的交互使用的是http协议。那么后端微服务之间。。。。。

Spring给我们提供了一个RestTemplate工具,可以方便的实现Http请求的发送。使用步骤如下:

1)注入RestTemplate到Spring容器

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

2)发起远程调用

//@RequiredArgsConstructor

//private final RestTemplate restTemplate;  
//@RequiredArgsConstructor和final配合使用,只为必要的参数建构造函数

// 2.查询商品
        // List<ItemDTO> items = itemService.queryItemByIds(itemIds);
        // 2.1 利用restTemplate发起http请求,得到http的响应
        ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
                "http://localhost:8081/items?ids={ids}",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<ItemDTO>>() {
                },
                Map.of("ids", CollUtil.join(itemIds, ","))
        );
        // 2.2 解析响应
        if (!response.getStatusCode().is2xxSuccessful()) {
            //查询失败,直接结束
            return;
        }
        List<ItemDTO> items = response.getBody();

测试了一下,这个 跨服务调用ok了。

三、服务治理

1. 服务远程调用存在的问题?

  • 服务调用者在写代码时,事先不知道服务提供者的地址,只有服务提供者服务启动,地址信息才会暴露给服务调用者
  • 地址这个事儿后续可以知道。服务提供者部署在一台服务器上,访问压力肯定超级大,所以会进行集群部署,那么服务调用者返回时,应该配置哪个地址进行访问呢
  • 地址也可以配置多个,然后服务调用者获取拼接访问地址也可。但是假如服务提供者其中一台服务器挂了(人只有在访问异常时才会知道是服务器挂了),服务调用者还跟之前一样的策略(比如随机访问固定的那几台服务器),是有概率访问到故障机的;或者服务提供者那边又重新启动了几台新的机器,除非人为奔走相告,服务调用者这边是感知不到的。那这运维人员发现故障再进行调整,或者调整完之后再传递信息给服务调用者,是有时间差的,可用性太差。

 2. 注册中心的原理

        cart-service它既是服务调用者,同时在某些情景下,它也是服务提供者;各服务之间只管发布自己、便于服务调用者寻找适合需求自己的服务,那么注册中心就是起一个中介的作用,你可以提供服务,就注册在我这里,注册表里会记录所有服务信息。这时服务调用者就从注册中心选择服务进行访问,但是应该访问哪个呢?访问时由负载均衡提供的策略指导。

        在注册中心的服务会定期向注册中心发请求,汇报自己的健康状况,名为心跳续约。当某个服务挂掉之后,注册中心会感知到,在提供服务列表会剔除这一服务,更新注册表,并将这一情况推送给服务调用者,名为推送变更。

服务治理中的三个角色分别是什么?

  • 服务提供者:暴露服务接口,供其它服务调用
  • 服务消费者:调用其它服务提供的接口
  • 注册中心:记录并监控微服务各实例状态,推送服务变更信息

消费者如何知道提供者的地址?

服务提供者会在启动时注册自己信息到注册中心,消费者可以从注册中心订阅和拉取服务信息

消费者如何得知服务状态变更?

服务提供者通过心跳机制向注册中心报告自己的健康状态,当心跳异常时注册中心会将异常服务剔除,并通知订阅了该服务的消费者

当提供者有多个实例时,消费者该选择哪一个?

消费者可以通过负载均衡算法,从多个实例中选择一个 

 3. Nacos注册中心

        Nacos是目前国内企业中占比最多的注册中心组件。它是阿里巴巴的产品,目前已经加入SpringCloudAlibaba中。

3.1 准备Nacos数据库

我们基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,需要将资料中的SQL文件导入到Docker中的MySQL容器

3.2 修改nacos/custom.env文件

        其中的nacos/custom.env文件中,有一个MYSQL_SERVICE_HOST也就是mysql地址,需要修改为你自己的虚拟机IP地址:

将nacos目录和nacos镜像nacos.tar上传到虚拟机/root下

加载镜像nacos.tar

docker load -i /root/nacos.tar 

查看镜像

 docker images 

3.3 启动nacos

docker run -d \
--name nacos \
--env-file /root/nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim

3.4 访问nacos 

账号:nacos;密码:nacos 

 4. 服务注册

4.1.添加依赖

item-servicepom.xml中添加依赖:

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

4.2.配置Nacos

  spring:
    cloud:
        nacos:
          server-addr: localhost:8848 //配置虚拟机地址

4.3.启动服务实例

启动两个服务实例,在nacos网页上验证:

 5. 服务发现和负载均衡

        消费者需要连接nacos以拉取和订阅服务,因此服务发现的前两步与服务注册是一样,后面再加上服务调用即可:

5.1 服务发现以及负载均衡-随机

private final DiscoveryClient discoveryClient;

/*注册中心查找实例方式*/
        //2.1根据服务名称获取服务的实例列表
        List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
        if (CollUtil.isEmpty(instances)) {
            return;
        }
        //2.2手写负载均衡,从实例列表中挑选一个实例
        ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
        //2.3利用restTemplate发起http请求,得到http的响应
                ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
                instance.getUri() + "/items?ids={ids}",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<ItemDTO>>() {
                },
                Map.of("ids", CollUtil.join(itemIds, ","))
        );
        // 2.2 解析响应
        if (!response.getStatusCode().is2xxSuccessful()) {
            //查询失败,直接结束
            return;
        }
        List<ItemDTO> items = response.getBody();

四、OpenFeign

1. 入门

OpenFeign是一个声明式的http客户端,是SpringCloud在Eureka公司开源的Feign基础上改造而来。其作用就是基于SpringMVC的常见注解,帮我们优雅的实现http请求的发送

官方地址:https://github.com/OpenFeign/feign

OpenFeign已经被SpringCloud自动装配,实现起来非常简单:

1)引入依赖,包括OpenFeign和负载均衡组件SpringCloudLoadBalancer

  <!--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)启用OpenFeign

cart-serviceCartApplication启动类上添加注解,启动OpenFeign功能:

 3)编写OpenFeign客户端

/**
 * @Author: EstellaQ
 * @Date: 2025/4/19 16:02
 * @Description: 商品模块feign远程调用
 **/
@FeignClient("item-service")
public interface ItemClient {
    @GetMapping("/items")
    List<ItemDTO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值