【SpringCloud】微服务1—服务注册中心Nacos

一、Nacos注册中心原理

Nacos主要用来解决微服务架构中的服务发现负载均衡健康检查配置管理集群管理等问题,帮助开发者更好地构建、部署和管理微服务应用。
在这里插入图片描述

1、问题:

  • item-service这么多实例,cart-service如何知道每一个实例的地址?
  • http请求要写url地址,cart-service服务到底该调用哪个实例呢?
  • 如果在运行过程中,某一个item-service实例宕机,cart-service依然在调用该怎么办?
  • 如果并发太高,item-service临时多部署了N台实例,cart-service如何知道新实例的地址?

2、注册中心、服务提供者、服务消费者三者间关系如下:

在这里插入图片描述

3、流程如下:

  • 服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心
  • 调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)
  • 调用者自己对实例列表负载均衡,挑选一个实例
  • 调用者向该实例发起远程调用

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

  • 服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)
  • 当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除
  • 当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表
  • 当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表

二、服务注册和发现

接下来,我们把item-service注册到Nacos,步骤如下:

  • 引入依赖
  • 配置Nacos地址

1、添加依赖:

在item-service的pom.xml中添加依赖:

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

可以发现,这里Nacos的依赖于服务注册和发现都是一致,这个依赖中同时包含了服务注册和发现的功能。因为任何一个微服务都可以调用别人,也可以被别人调用,即可以是调用者,也可以是提供者。

2、配置Nacos:

在item-service的application.yml中添加nacos地址配置:

spring:
  application:
    name: item-service # 服务名称
  cloud:
    nacos:
      server-addr: 192.168.150.101:8848 # nacos地址

三、OpenFeign(实现服务之间的远程调用)

我们利用Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。但是远程调用的代码太复杂了。而且这种调用方式,与原本的本地方法调用差异太大,编程时的体验也不统一,一会儿远程调用,一会儿本地调用。
我们必须想办法改变远程调用的开发模式,让远程调用像本地方法调用一样简单。而这就要用到OpenFeign组件

为了避免每个服务都需要添加OpenFeign的依赖和配置,使用公共模块来解决重复编码的问题。
在这里插入图片描述

1、创建公共模块:

在这里插入图片描述

2、引入依赖:

<dependencies>
        <!--open feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- load balancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

3、启用OpenFeign:

在每一个服务的的启动类上添加注解 @EnableFeignClients,启动OpenFeign功能,例如:
在这里插入图片描述

4、编写OpenFeign客户端:

package com.hmall.cart.client;

import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient("item-service") // !!!
public interface ItemClient {

    @GetMapping("/items")
    List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}

这里只需要声明接口,无需实现方法。接口中的几个关键信息:

  • @FeignClient(“item-service”) :声明服务名称
  • @GetMapping :声明请求方式
  • @GetMapping(“/items”) :声明请求路径
  • @RequestParam(“ids”) Collection ids :声明请求参数
  • List :返回值类型

5、更换连接池:

Feign底层发起http请求,依赖于其它的框架。其底层支持的http客户端实现包括:

  • HttpURLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

因此我们通常会使用带有连接池的客户端来代替默认的HttpURLConnection。比如,我们使用OK Http.

引入依赖:

<!--OK http 的依赖 -->
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
</dependency>

开启连接池:

feign:
  okhttp:
    enabled: true # 开启OKHttp功能

6、日志配置:

OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

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

package com.hmall.api.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;
    }
}

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

  • 局部生效:在某个FeignClient中配置,只对当前FeignClient生效
@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
  • 全局生效:在@EnableFeignClients中配置,针对所有FeignClient生效。
@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)

四、配置管理

目前,依然还有几个问题需要解决:

  • 网关路由在配置文件中写死了,如果变更必须重启微服务
  • 某些业务配置在配置文件中写死了,每次修改都要重启服务
  • 每个微服务都有很多重复的配置,维护成本高

这些问题都可以通过统一的配置管理器服务解决。而Nacos不仅仅具备注册中心功能,也具备配置管理的功能:
在这里插入图片描述

微服务共享的配置可以统一交给Nacos保存和管理,在Nacos控制台修改配置后,Nacos会将配置变更推送给相关的微服务,并且无需重启即可生效,实现配置热更新。
网关的路由同样是配置,因此同样可以基于这个功能实现动态路由功能,无需重启网关即可修改路由配置。

1、配置共享:

查看每个微服务的yaml文件,发现有几个方面都是重复配置的,有jdbc的配置,日志logs的配置,还有swaager的配置等等。

我们可以把微服务共享的配置抽取到Nacos中统一管理,这样就不需要每个微服务都重复配置了。分为两步:

  • 在Nacos中添加共享配置
  • 微服务拉取配置

在这里插入图片描述
其中详细的配置如下:

# spring
spring:
  datasource:
    url: jdbc:mysql://${hm.db.host:192.168.74.128}:${hm.db.port:3306}/${hm.db.database}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: ${hm.db.un:root}
    password: ${hm.db.pw:123}

# mybatis-plus
mybatis-plus:
  # 详细配置
  configuration:
    # 表示默认的枚举类型处理器,用于处理枚举类型的数据
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
  # 全局配置
  global-config:
    # 数据库配置
    db-config:
      # 表示更新策略为非空,即在更新数据时,如果某个字段为空,则不更新该字段
      update-strategy: not_null
      # 表示ID类型为自动生成,即在插入数据时,会自动为该字段生成一个唯一的ID
      id-type: auto

注意这里的jdbc的相关参数并没有写死,例如:

  • 数据库ip:通过 h m . d b . h o s t : 192.168.74.128 配置了默认值为 192.168.74.128 ,同时允许通过 {hm.db.host:192.168.74.128}配置了默认值为192.168.74.128,同时允许通过 hm.db.host:192.168.74.128配置了默认值为192.168.74.128,同时允许通过{hm.db.host}来覆盖默认值
  • 数据库端口:通过 h m . d b . p o r t : 3306 配置了默认值为 3306 ,同时允许通过 {hm.db.port:3306}配置了默认值为3306,同时允许通过 hm.db.port:3306配置了默认值为3306,同时允许通过{hm.db.port}来覆盖默认值
  • 数据库database:可以通过${hm.db.database}来设定,无默认值

然后是统一的日志配置,命名为shared-log.yaml,配置内容如下:

logging:
  level:
    com.hmall: debug
  pattern:
    dateformat: HH:mm:ss:SSS
  file:
    path: "logs/${spring.application.name}"

然后是统一的swagger配置,命名为shared-swagger.yaml,配置内容如下:

knife4j:
  enable: true
  openapi:
    title: ${hm.swagger.title:黑马商城接口文档}
    description: ${hm.swagger.description:黑马商城接口文档}
    email: ${hm.swagger.email:zhanghuyi@itcast.cn}
    concat: ${hm.swagger.concat:虎哥}
    url: https://www.itcast.cn
    version: v1.0.0
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - ${hm.swagger.package}

注意,这里的swagger相关配置我们没有写死,例如:

  • title:接口文档标题,我们用了${hm.swagger.title}来代替,将来可以有用户手动指定
  • email:联系人邮箱,我们用了${hm.swagger.email:zhanghuyi@itcast.cn},默认值是zhanghuyi@itcast.cn,同时允许用户利用 ${hm.swagger.email}来覆盖。

2、拉取共享配置:

接下来,我们要在微服务拉取共享配置。将拉取到的共享配置与本地的application.yaml配置合并,完成项目上下文的初始化。
不过,需要注意的是,读取Nacos配置是SpringCloud上下文(ApplicationContext)初始化时处理的,发生在项目的引导阶段。然后才会初始化SpringBoot上下文,去读取application.yaml。
也就是说引导阶段,application.yaml文件尚未读取,根本不知道nacos 地址,该如何去加载nacos中的配置文件呢?

SpringCloud在初始化上下文的时候会先读取一个名为bootstrap.yaml(或者bootstrap.properties)的文件,如果我们将nacos地址配置到bootstrap.yaml中,那么在项目引导阶段就可以读取nacos中的配置了。
在这里插入图片描述
因此,微服务整合Nacos配置管理的步骤如下:

1)引入依赖:
在cart-service模块引入依赖:

  <!--nacos配置管理-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>
  <!--读取bootstrap文件-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
  </dependency>

2)新建bootstrap.yaml
在cart-service中的resources目录新建一个bootstrap.yaml文件:
在这里插入图片描述
内容如下:

spring:
  application:
    name: cart-service # 服务名称
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: 192.168.150.101 # nacos地址
      config:
        file-extension: yaml # 文件后缀名
        shared-configs:      # 共享配置
          - dataId: shared-jdbc.yaml    # 共享mybatis配置
          - dataId: shared-log.yaml     # 共享日志配置
          - dataId: shared-swagger.yaml # 共享日志配置

3)修改application.yaml
由于一些配置挪到了bootstrap.yaml,因此application.yaml需要修改为:

server:
  port: 8082
feign:
  okhttp:
    enabled: true # 开启OKHttp连接池支持
hm:
  swagger:
    title: 购物车服务接口文档
    package: com.hmall.cart.controller
  db:
    database: hm-cart

3、配置热更新:

有很多的业务相关参数,将来可能会根据实际情况临时调整。例如购物车业务,购物车数量有一个上限,默认是10,对应代码如下:
在这里插入图片描述
现在这里购物车是写死的固定值,我们应该将其配置在配置文件中,方便后期修改。
但现在的问题是,即便写在配置文件中,修改了配置还是需要重新打包、重启服务才能生效。能不能不用重启,直接生效呢?
这就要用到Nacos的配置热更新能力了,分为两步:

  • 在Nacos中添加配置
  • 在微服务读取配置

首先,我们在nacos中添加一个配置文件,将购物车的上限数量添加到配置中:
在这里插入图片描述
注意文件的dataId格式:

[服务名]-[spring.active.profile].[后缀名]

文件名称由三部分组成:

  • 服务名:我们是购物车服务,所以是cart-service
  • spring.active.profile:就是spring boot中的spring.active.profile,可以省略,则所有profile共享该配置
  • 后缀名:例如yaml

这里我们直接使用cart-service.yaml这个名称,则不管是dev还是local环境都可以共享该配置。
配置内容如下:

hm:
  cart:
    maxAmount: 1 # 购物车商品数量上限

接着,我们在微服务中读取配置,实现配置热更新。
在cart-service中新建一个属性读取类:
在这里插入图片描述
代码如下:

package com.hmall.cart.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {
    private Integer maxAmount;
}

接着,在业务中使用该属性加载类:
在这里插入图片描述
无需重启服务,配置热更新就生效了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值