微服务

单体项目缺点:

随着项目的开发, 单体服务的构建产物会愈来愈大, 随之带来的问题就是项目的构建, 部署和发布会越来越慢


微服务优点:

微服务适用于敏捷开发, 各个功能的依赖不会互相影响


微服务开发技术:

  • 服务网关 (请求路由, 负载均衡)
  • 注册中心 (拉取或注册服务)
  • 配置中心 (拉取配置信息)
  • 分布式缓存
  • 分布式搜索
  • 消息队列
  • 分布式日志
  • 系统监控-链路追踪

部署技术:

  • CL/CI
  • Docker
  • K8s

可分为:

  • 微服务技术

    • 微服务治理
    • 微服务保护
    • 分布式事务
  • 缓存技术

    • 分布式缓存
    • 多级缓存
    • Redis 集群
  • 异步通信技术

    • 异步通信
    • 可靠消息服务
  • 搜索技术
  • DevOps

微服务技术

国内流行的微服务技术框架:

  • SpringCloud
  • 阿里巴巴 Dubbo
  • SpringCloudAlibaba

技术对比:

DubboSpringCloudSpringCloudAlibaba
注册中心ZooKeeper, NacosEureka, ConsulNacos, Eureka
服务远程调用Dubbo 协议Feign (http 协议)Dubbo, Feign
配置中心SpringCloudConfigSpringCloudConfig, Nacos
服务网关SpringCloudGatewaySpringCloudGateway, Zuul
服务监控和保护dubbo-adminHystrixSentinel

一般的技术选型:

  • SpringCloud + Feign
  • SpringCloudAlibaba + Feign
  • SpringCloudAlibaba + Dubbo
  • Dubbo 原始模式

服务拆分

服务拆分注意事项:

  • 单一职责: 不同微服务, 不要重复开发相同的业务
  • 数据独立: 不要访问其它微服务数据库
  • 面向服务: 将自己的业务暴露为接口, 供其它服务调用

消费者与服务者

服务提供者: 一次调用中, 被其它微服务调用的服务 (提供接口)

服务消费者: 一次调用中, 调用其它微服务的服务 (调用服务)

在实际的代码开发中, 我们需要知道服务提供者的访问地址(分布式架构, 意味着提供者的访问地址随时变化), 如何知道提供者的接口地址? 通过注册中心来发现提供者地址


注册中心

Eureka 注册中心

在 EureKa 架构中, 微服务角色有两类:

  • EurekaServer 服务端, 注册中心

    • 记录服务信息
    • 心跳记录
  • EurekaClient 客户端

    • Provider 服务提供者

      • 注册自己的信息到 EurekaServer 发送心跳
      • 每隔一段时间向 EurekaServer 发送心跳
    • consumer 服务消费者

      • 根据服务名称从 EurekaServer 拉取服务列表
      • 基于服务列表做负载均衡, 选中一个微服务后发起远程调用

搭建注册中心

创建一个项目模块 eureka-service, 用于创建EurekaServer 服务端, 注册中心

添加依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

配置 application.yml

server:
  port: 10086
spring:
  application:
    name: eureka-server
  cloud:
    # 避免虚拟机带来的报错, 忽略虚拟网卡
    inetutils:
      ignored-interfaces: 'VMware Virtual Ethernet Adapter for VMnet1,VMware Virtual Ethernet Adapter for VMnet8'

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
    # 不向注册中心注册自己。
    register-with-eureka: false
    fetch-registry: false

最后, 在启动类中添加启用注解:

@EnableEurekaServer

启动后, 访问 localhost:10086 查看注册中心


服务注册 - 配置客户端

为其拆分的服务加入依赖 spring-cloud-starter-netflix-eureka-client

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置项目

spring:
  application:
    name: userservice

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

可复制实例, 模拟负载均衡, 在 IDEA 服务栏中, 选中运行的实例, 右键复制实例, 在 VM Options 中添加选型 -Dserver.port=8083 以修改服务端口, 以避免复制实例端口冲突


服务发现

服务发现须在启动类中添加方法 restTemplate, 并添加注解 @LoadBalanced

@LoadBalanced 为负载均衡
@Bean
  @LoadBalanced
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

然后, 就可通过 http://[服务名称]/[接口路径], 即将实际的域名改为微服务名称即可对服务提供者发起调用

String requestUrl = "http://user-service/user/" + order.getUserId();
User user = restTemplate.getForObject(requestUrl, User.class);

Ribbon 负载均衡

负载均衡流程:

Robbion 负载均衡流程.png

负载均衡策略:

Robbion 负载均衡策略.png


自定义负载均衡

可通过 IRule 实现来修改负载均衡规则, 有两种方式:

  • 代码修改
  • 配置修改

代码修改:

在启动类中, 定义一个新的 IRule:

@Bean
public IRule randomRule(){
  return new RandomRule();
} 

配置方式, 在 application.yml 中添加以下配置:

eureka:
  client:
    user-service:
      ribbon:
        # 负载均衡规则
        NFLoadBalanceRuleClassName: com.netflix.loadbalance.RandomRule

两种方法的生效范围不同,

代码修改的方法作用于全局, 所有调用的所有服务的负载均衡规则都将被修改

而配置方式作用于局部, 可根据不同的调用服务来配置不同的负载均衡规则


饥饿加载

Ribbon 默认采用懒加载, 即第一次访问时才会去创建 LoadBalanceClient, 请求时间长

饥饿加载会在项目启动时创建, 降低第一次访问的耗时

通过配置开启饥饿加载:

eureka:
  ribbon:
    eager-load:
      enable: true
      client: user-service # 对 user-service 进行饥饿加载

Nacos 注册中心

Nacos 是阿里巴巴的产品, 现在是 SpringCloud 中的一个组件

相比 Eureka 功能更加丰富, 在国内受欢迎程度较高

Nacos 官网


Nacos 安装

我是把 Nacos 部署至 Linux 虚拟机中, 用的是 Docker 运行

单机启动命令:

务必注意 Nacos 版本
docker run --name nacos-standalone \
                -e MODE=standalone \
                -p 8080:8080 \
                -p 8848:8848 \
                -p 9848:9848 \
                -d nacos/nacos-server:v2.5.1

安装完成后, 访问其对应 http://[ip]:8848/nacos 进入 Nacos 控制台


服务注册到 Nacos

Nacos 与 Eureka 不能共存, 在引入 Nacos 时, 注意去掉 Eureka 相关依赖


在父级工程中添加 spring-cloud-alibaba 依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

在服务中添加服务发现 (服务注册)依赖, 即 Nacos 客户端

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

在服务中的 application.yml 中配置 Nacos 客户端

spring:
  cloud:  
    nacos:
      server-addr: 192.168.233.128:8848

Nacos 服务分级存储模型

Nacos 分级存储模型.png

Nacos 分级存储模型分三级:

  • 一级服务 (服务接口)
  • 二级集群 (服务器集群, 例如广州, 上海)
  • 三级实例 (服务器)

集群调用负载均衡

服务跨集群调用问题: 跨集群调用延迟较高

我们希望服务调用尽可能选择本地集群服务, 当本地集群不可访问时, 再去访问其它集群

若没配置集群, 则服务默认在 DEFAULT 集群中

我们可以通过 application.yml 配置服务所属集群

spring:
  cloud:
    nacos:
      server-addr: 192.168.233.128:8848
       discovery:
         # 配置集群
         cluster-name: CD # 集群 - 成都

要想优先访问本集群, 还需使用 Nacos 的负载均衡

user-service: # 服务名
  ribbon:
    # 负载均衡规则
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

Nacos 负载均衡策略:

  1. 优先选择同集群服务实例列表
  2. 本地集群找不到提供者, 才去其它集群寻找, 并且会报警告
  3. 确定了可用实例列表后, 再采用随机负载均衡挑选实例

权重负载均衡

在实际部署中会出现这样的问题:

服务器设备性能有差异, 部分实例机器性能号, 另一部分差

我们希望性能好的机器去承担更多的用户请求


可通过 Nacos 注册中心选择实例并配置权重, 权重范围 0 ~ 1 之间

实例的权重控制:

  • Nacos 控制台可以设置实例的权重值
  • 同集群内的多个实例, 权重越高被访问的频率越高
  • 权重为 0 则完全不会被访问

环境隔离

软件工程的各种环境:

  • 开发环境
  • 测试环境
  • 灰度环境
  • 生产环境

为了实现各种环境的隔离, Nacos 使用 namespace 来隔离

Nacos 中服务存储的最外层都是一个名为 namespace 的东西, 用来做最外层隔离

Nacos 环境隔离.png

在 Nacos 控制台中创建命名空间, 我们在这里可以创建一个为 dev 的命名空间

创建完成后, 会有一个命名空间 ID

我们需要将命名空间 ID 配置到服务中

spring:
  cloud:
    nacos:
      server-addr: 192.168.233.128:8848
      discovery:
        cluster-name: CD
        namespace: edc5e1fe-a6f4-4c33-951e-a0f2f4a25d00 # 命名空间 ID

临时/非临时实例

Nacos 细节.png

我们可以将服务改成非临时实例, 这样, Nacos 会主动查询服务实例的健康状况

配置服务实例为非临时实例:

spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

总结

Nacos 与 Eureka 的共同点:

  • 支持服务注册和服务拉取
  • 支持服务提供者以心跳方式做健康检测

Nacos 与 Eureka 的区别:

  • Nacos支持服务端主动检测提供者状态

    • 临时实例采用心跳模式
    • 非临时实例采用主动检测模式
  • 临时实例心跳不正常会被剔除, 非临时实例则不会被剔除
  • Nacos 支持服务列表变更的消息推送模式, 服务列表更新更及时
  • Nacos 集群默认采用 AP 方式, 当集群中存在非临时实例时, 采用 CP 模式
  • Eureka 采用 AP 方式

该部分仅登录用户可见

最后修改:2025 年 07 月 03 日
如果觉得我的文章对你有用,请随意赞赏