SpringCloud是目前国内使用最广泛的微服务框架。

官网地址: https:/ /spring.io/ projects/spring-cloud.

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即

用体验:

【微服务】-拆分原则、远程调用、服务治理_微服务

服务拆分原则

什么时候拆分

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

渐拆分。

●确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免

后续拆分的麻烦。

怎么拆分

从拆分目标来说,要做到:

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

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

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

拆分服务

工程结构有两种

  • 独立Project
  • Maven聚合

远程调用

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

注入RestTemplate到Spring容器

【微服务】-拆分原则、远程调用、服务治理_微服务_02

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

发起远程调用

【微服务】-拆分原则、远程调用、服务治理_微服务_03

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, ","))
        );

        if(!response.getStatusCode().is2xxSuccessful()){
            return;
        }
        List<ItemDTO> items = response.getBody();
        if (CollUtils.isEmpty(items)) {
            return;
        }

服务治理

注册中心原理

因为RestTemplate请求的时候将调用地址写固定了,容易出问题,所以我们需要对上面的代码进行改进

服务治理中的三个角色

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

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

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

中心订阅和拉取服务信息

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

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

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

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

【微服务】-拆分原则、远程调用、服务治理_服务发现_04

【微服务】-拆分原则、远程调用、服务治理_服务发现_05

Nacos注册中心

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

使用docker搭建Nacos注册中心

【微服务】-拆分原则、远程调用、服务治理_服务发现_06

服务注册

引入nacos discovery

【微服务】-拆分原则、远程调用、服务治理_List_07

配置Nacos地址

【微服务】-拆分原则、远程调用、服务治理_List_08

【微服务】-拆分原则、远程调用、服务治理_服务发现_09

【微服务】-拆分原则、远程调用、服务治理_List_10

服务发现

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

引入nacos discovery

配置Nacos地址

服务发现

【微服务】-拆分原则、远程调用、服务治理_List_11

 // 1.获取商品id
        Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
        // 2.查询商品
        //根据服务名称获取服务实例列表
        List<ServiceInstance> instances = discoveredResource.getInstances("item-service");
        if(CollUtil.isEmpty(instances)){
            return;
        }

        //手写负载均衡
        ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));

        ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
                instance.getUri()+"/items?ids={ids}",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<ItemDTO>>() {
                },
                Map.of("ids", CollUtil.join(itemIds, ","))
        );