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 应用(调用方)
通过这个案例,我们将验证两种调用流程:
- 用户调用 Echo 应用的接口 → Echo 通过服务发现获取 NodeJS 服务地址 → 直接调用 NodeJS
- 用户通过 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