1. 概述

Spring Cloud 提供了丰富的功能库,包括客户端负载均衡、服务注册/发现、并发控制和配置中心等。但在微服务架构中,使用不同语言和框架构建的多语言服务(Polyglot Services)已是常态。那么如何让整个生态都能享受 Spring Cloud 的红利?Spring Cloud Netflix Sidecar 就是为此设计的解决方案。

本文将通过实战案例深入解析 Spring Cloud Sidecar 的核心原理与应用场景。

2. 什么是 Spring Cloud Sidecar?

Cloud Netflix Sidecar 的设计灵感来源于 Netflix Prana,它作为非 JVM 服务的代理工具,解决了两大核心问题:

服务注册与发现集成:让非 JVM 服务能注册到服务注册中心 生态互操作性:通过主机查找或 Zuul 代理访问配置中心和其他服务

要集成非 JVM 服务,只需满足一个硬性要求:提供标准健康检查接口。其他复杂工作全部由 Sidecar 包办。

3. 实战案例

我们的案例包含三个应用:

  • NodeJS 实现的 /hello 接口
  • Spring Sidecar 应用(代理服务)
  • Spring Echo 应用(调用方)

通过这个案例,我们将验证两种调用流程:

  1. 用户调用 Echo 应用的接口 → Echo 通过服务发现获取 NodeJS 服务地址 → 直接调用 NodeJS
  2. 用户通过 Zuul 代理直接访问 NodeJS 服务

3.1. NodeJS Hello 接口

创建 hello.js 文件,使用 Express 框架实现三个接口:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.get('/health', (req, res) => {
    res.send({ "status":"UP"})
})

app.get('/hello/:me', (req, res) => {
    res.send('Hello ' + req.params.me + '!')
})

app.listen(port, () => {
    console.log(`Hello app listening on port ${port}`)
})

安装依赖并启动:

npm install express
node hello.js

验证接口:

curl http://localhost:3000/hello/baeldung
Hello baeldung!

curl http://localhost:3000/health
{"status":"UP"}

3.2. Sidecar 应用

踩坑预警:当前 Sidecar 最新版(2.2.10.RELEASE)仅支持 Spring Boot 2.3.12.RELEASE,最新版 Spring Boot 暂不兼容!

添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-sidecar</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>

主类启用 Sidecar:

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

关键配置(application.yml):

server:
  port: 8084
spring:
  application:
    name: sidecar
eureka:
  instance:
    hostname: localhost
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka
    healthcheck:
      enabled: true
sidecar:
  port: 3000
  health-uri: http://localhost:3000/health

启动后,Sidecar 会自动将 NodeJS 服务注册为 "hello" 服务到 Eureka。验证地址: http://localhost:8084/hosts/sidecar

简单粗暴的原理@EnableSidecar 注解同时启用了 @EnableCircuitBreaker@EnableZuulProxy,让 Sidecar 天生具备 Hystrix 和 Zuul 能力。

3.3. Echo 应用实现

添加依赖(版本需与 Sidecar 保持一致):

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

主类配置:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EchoApplication {
    // ...
}

配置文件(application.yml):

server:
  port: 8085
spring:
  application:
    name: echo
eureka:
  instance:
    hostname: localhost
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka

验证服务发现:

curl http://localhost:8084/hosts/echo

通过 Zuul 代理访问 NodeJS 服务:

curl http://localhost:8085/sidecar/hello/baeldung
Hello baeldung!

服务发现调用方式:创建控制器注入 DiscoveryClient

@Autowired
DiscoveryClient discoveryClient;

@GetMapping("/hello/{me}")
public ResponseEntity<String> echo(@PathVariable("me") String me) {
    List<ServiceInstance> instances = discoveryClient.getInstances("sidecar");
    if (instances.isEmpty()) {
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("hello service is down");
    }
    String url = instances.get(0).getUri().toString();
    return ResponseEntity.ok(restTemplate.getForObject(url + "/hello/" + me, String.class));
}

重启后测试:

curl http://localhost:8085/hello/baeldung
Hello baeldung!

跨服务调用验证:

curl http://localhost:8084/echo/hello/baeldung
Hello baeldung!

4. 总结

本文通过 NodeJS + Spring Boot 的混合架构案例,展示了 Spring Cloud Sidecar 的核心价值:

  • 为非 JVM 服务提供 Spring Cloud 生态接入能力
  • 支持服务注册/发现、健康检查、配置中心等核心功能
  • 通过 Zuul 代理实现服务路由

完整代码示例请查阅 GitHub 仓库:spring-cloud-netflix-sidecar


原始标题:Introduction to Spring Cloud Sidecar