乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 微服务与 Spring Cloud 概述

    • 微服务与 Spring Cloud 概述
  • 第2章 服务注册与发现

    • Eureka 服务注册与发现
    • Consul 服务注册与发现
  • 第3章 客户端负载均衡

    • Ribbon 客户端负载均衡
    • Spring Cloud LoadBalancer
  • 第4章 声明式服务调用

    • Feign 声明式 HTTP 客户端
    • OpenFeign 高级特性与 Spring Cloud 集成
  • 第5章 服务容错与熔断

    • Resilience4j 服务容错与熔断
    • Sentinel 流量控制与熔断降级
  • 第6章 配置中心

    • Spring Cloud Config 配置中心
  • 第7章 API 网关

    • Spring Cloud Gateway 现代化 API 网关
    • Zuul 网关(已进入维护模式)
  • 第8章 消息驱动的微服务

    • Spring Cloud Stream 消息驱动的微服务
  • 第9章 分布式追踪与监控

    • Sleuth + Zipkin 分布式链路追踪
  • 第10章 最佳实践与面试考点

    • Spring Cloud 最佳实践与面试考点

Consul 服务注册与发现

导学

白歌成功用 Eureka 搭建了服务注册中心,但产品经理孔蓝提出了新需求:"公司还有一部分物流系统是 Go 语言写的,Python 写的爬虫服务也需要注册进来,Eureka 能搞定吗?"

白歌查了一下:Eureka 的客户端仅支持 Java(虽然有 REST API,但 Go/Python 团队需要自己实现注册逻辑)。CTO 大翔拍板:"用 Consul,原生多语言支持,还能做健康检查和 KV 配置。"


定位与问题场景

Eureka 解决了 Java 微服务的注册发现问题,但在以下场景有局限性:

场景Eureka 的限制Consul 的优势
多语言异构系统仅 Java 客户端成熟原生 HTTP/DNS/gRPC 接口,任何语言可调用
健康检查仅依赖客户端心跳支持 HTTP/TCP/Script/gRPC 多维度健康检查
多数据中心需手动配置 Region/Zone原生多数据中心(Multi-Datacenter)支持
配置管理不支持内置 KV Store,可作简单配置中心

Consul 是 HashiCorp 公司开发的服务网格解决方案,基于 Raft 共识协议保证强一致性(CP 系统)。


Consul 核心原理

架构与角色

角色职责
Consul Server集群核心,基于 Raft 选举 Leader,负责存储注册信息、处理查询、同步数据。生产环境建议 3 台或 5 台
Consul Agent运行在每台节点的守护进程,负责转发请求、执行健康检查、维护本地缓存
Consul Client应用通过 HTTP API 或 DNS 接口查询服务

健康检查机制

Consul 的健康检查远比 Eureka 丰富:


Consul vs Eureka 核心对比

维度EurekaConsul
CAPAP(高可用 + 分区容错)CP(强一致 + 分区容错)
一致性协议Peer to Peer 复制Raft 共识协议
健康检查仅客户端心跳HTTP / TCP / Script / gRPC / TTL
多数据中心需要额外配置原生 WAN Gossip 支持
KV 存储无内置 KV Store
语言支持Java(REST API 需自行实现)HTTP/DNS/gRPC 原生多语言
CAP 权衡网络分区时仍可注册新服务网络分区时非 Leader 分区不可写

选型建议:纯 Java 生态 + 对一致性要求不高 → Eureka;多语言异构系统 + 需要强一致性 + 健康检查 → Consul;需要注册中心 + 配置中心一体化 → Nacos。


完整示例:飞翔科技多语言服务注册

场景描述

飞翔科技有三个异构服务需要注册到 Consul:

  • feixiang-order-service(Java / Spring Boot)
  • feixiang-logistics-service(Go 语言物流服务)
  • feixiang-crawler-service(Python 爬虫服务)

操作前后对比:

维度引入 Consul 前引入 Consul 后
异构语言注册Go/Python 服务手动维护 IP 列表统一通过 Consul API 注册
健康检查人工巡检自动 HTTP/TCP 多维度检查
服务发现各语言各自实现统一 DNS / HTTP API

步骤一:启动 Consul(Docker)

docker run -d --name consul-server \
  -p 8500:8500 \
  -p 8600:8600/udp \
  consul:1.15 agent -server -bootstrap-expect=1 -ui -client=0.0.0.0

访问 Consul UI:http://localhost:8500

步骤二:Java 服务注册(Spring Cloud Consul)

依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置:

spring:
  application:
    name: feixiang-order-service
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        health-check-path: /actuator/health
        health-check-interval: 15s
        prefer-ip-address: true   # 使用 IP 而非主机名注册

启动类无需特殊注解,@SpringBootApplication + 依赖即可自动注册。

步骤三:Go 物流服务注册(Consul HTTP API)

package main

import (
    "encoding/json"
    "net/http"
    "consulapi "github.com/hashicorp/consul/api"
)

func main() {
    config := consulapi.DefaultConfig()
    client, _ := consulapi.NewClient(config)

    // 注册服务
    registration := &consulapi.AgentServiceRegistration{
        ID:   "feixiang-logistics-1",
        Name: "feixiang-logistics-service",
        Port: 9090,
        Check: &consulapi.AgentServiceCheck{
            HTTP:     "http://localhost:9090/health",
            Interval: "10s",
            Timeout:  "3s",
        },
    }
    client.Agent().ServiceRegister(registration)

    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
        json.NewEncoder(w).Encode(map[string]string{"status": "UP"})
    })

    http.ListenAndServe(":9090", nil)
}

步骤四:Java 订单服务通过 Consul 发现物流服务

@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

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

@RestController
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/order/ship/{orderId}")
    public Map<String, Object> shipOrder(@PathVariable String orderId) {
        // 服务名即可调用,无需关心是 Java 还是 Go
        return restTemplate.getForObject(
            "http://feixiang-logistics-service/ship/" + orderId,
            Map.class
        );
    }
}

步骤五:验证

curl http://localhost:8080/order/ship/ORD-2024-001
# 返回:{"orderId":"ORD-2024-001", "status":"SHIPPED", "carrier":"SF Express"}

在 Consul UI 中可以看到 Java 服务和 Go 服务均列为健康实例。


易错场景

1. Consul Agent 未启动导致注册失败

Spring Cloud Consul 默认连接 localhost:8500,如果本地没有运行 Consul Agent,应用启动时会报 ConnectException。解决方案:每个节点运行一个 Consul Agent(开发环境可用 consul agent -dev)。

2. 健康检查路径配置错误

Consul 的健康检查默认使用 spring.cloud.consul.discovery.health-check-path(默认 /actuator/health)。如果项目未引入 Actuator 依赖,所有实例都会被标记为 critical。

3. Raft 协议要求奇数节点

Consul Server 集群节点数必须是奇数(推荐 3 或 5),否则可能发生脑裂(Split Brain)导致选举失败。

4. Consul 的 CP 特性在网络分区时的表现

当 Consul 集群发生网络分区时,非 Leader 分区无法处理写操作(注册、注销),直到分区恢复。这与 Eureka 的 AP 行为完全相反。


面试考点

Consul 的 Raft 协议如何保证一致性?

Consul Server 集群通过 Raft 协议选举一个 Leader,所有写操作必须经过 Leader,Leader 将日志复制到 Follower(过半确认即提交)。读操作可以从任意节点读取(可能有短暂过期数据)。当 Leader 宕机时,Follower 发起新一轮选举,任期号递增,保证不会出现两个 Leader。

Consul 健康检查有哪几种?各适用什么场景?

  • HTTP:定期 GET 健康端点,检查返回码,适合 Web 服务
  • TCP:定期尝试 TCP 连接,检查端口是否可达,适合非 HTTP 服务
  • Script:执行自定义脚本,根据退出码判断,适合复杂逻辑(如检查数据库连接、磁盘空间)
  • gRPC:适用于 gRPC 服务的健康检查
  • TTL:应用主动上报状态,适合无法被外部探测的服务

Eureka(AP)vs Consul(CP):如何选择?

如果优先保证服务可用性——即使注册中心网络分区,各服务仍能正常注册和调用 → 选 Eureka。如果优先保证数据一致性——宁可拒绝注册也不能返回过期实例列表 → 选 Consul。国内互联网公司通常优先可用性(AP),金融/支付系统倾向于强一致性(CP)。


小结

Consul 在 Eureka 的基础上,通过原生多语言支持、多维度健康检查、多数据中心、内置 KV Store 等特性,提供了更全面的服务治理能力。它的 CP 特性使其在强一致性场景下比 Eureka 更有优势,但运维复杂度也更高。下一章我们来看注册中心返回了多个实例后,消费者如何选择调用哪个——客户端负载均衡。

上一页
Eureka 服务注册与发现