负载平衡 (ribbon) 和路由 (zuul) Spring REST API (Spring Data JPA) 请求到同一服务的多个副本
Posted
技术标签:
【中文标题】负载平衡 (ribbon) 和路由 (zuul) Spring REST API (Spring Data JPA) 请求到同一服务的多个副本【英文标题】:Load balancing (ribbon) and routing (zuul) Spring REST API (Spring Data JPA) requests to multiple copies of same service 【发布时间】:2017-01-15 19:06:21 【问题描述】:我似乎找不到以下场景的明确示例/解决方案;任何帮助/信息将不胜感激!
我有一个 Spring REST API 服务,它使用 Spring Data JPA 连接到后端数据库服务器。我在多台机器上运行这个完全相同的服务,并且我有一个反向代理,它将客户端请求(使用 Netflix Zuul)路由到这些 API 服务,以便访问数据库中的数据。但是,我想对请求进行负载平衡(通过反向代理和可能的 Netflix 功能区),以便每个请求仅发送到单个 API 服务器(以负载平衡的方式)。
Spring Data JPA 根据我定义的实体类和其余存储库自动配置端点。一种解决方案是在反向代理上为 API 服务上的每个端点生成一个等效端点,然后使用 Ribbon 客户端分别对每个端点进行负载平衡。但是,这似乎不是合适的解决方案。
我的问题是,Netflix Zuul 或 Ribbon 是否提供任何功能来处理这种情况?本质上,我希望能够设置一个 YAML 配置,它只是告诉 Zuul 使用功能区客户端并根据可用的 listOfServers 功能区配置自动将所有请求负载平衡到给定端点。
application.yml
例子:
DatabaseAPI:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8080, localhost:8181, localhost:8282
ServerListRefreshInterval: 15000
zuul:
routes:
data:
path: /db/**
ServiceId: DatabaseAPI
现在,例如,我希望 /db/** 的每个请求都以循环方式发送到服务器列表中的一个可用服务器。注意:使用此示例配置,每个请求都会同时发送到所有可用服务器。我只希望其中一个接收每个请求。
【问题讨论】:
我也遇到了同样的难题,你找到解决办法了吗? 除了我在上面的问题中建议的有点不合理的可能解决方案之外,不,我还没有找到一个好的解决方案!我暂时把它放在一边,但我希望能尽快找到解决方案。 【参考方案1】:默认情况下,Zuul 使用 Ribbon 来定位要通过发现转发到的实例(例如,在您的情况下是 Eureka)。因此,在网关应用程序 (Zuul) 中,您不需要在类路径中有 Ribbon。
如果您没有通过 Zuul 看到实例之间的负载平衡,请尝试增加请求(例如 > 200 个请求)
【讨论】:
【参考方案2】:我发现这实际上是为你自动配置的,如果你在类路径上有 Zuul 和 Ribbon。基本上,我创建了三个这样的项目:
尤里卡服务器
bootstrap.properties
spring.application.name=eureka-server
application.properties
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
尤里卡服务器
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer
public static void main(String[] args)
SpringApplication.run(EurekaServer.class, args);
微服务项目
bootstrap.properties
spring.application.name=microservice
application.properties
server.port=8081
MsApplication
@SpringBootApplication
@EnableDiscoveryClient
public class MsApplication
public static void main(String[] args)
SpringApplication.run(MsApplication.class, args);
@RestController
class DummyController
@Value("$server.port")
private int serverPort;
@GetMapping("/")
public String home()
return "Microservice on port: " + serverPort;
@GetMapping("/test")
public String someLogic()
return "Some hard stuff is done here";
微服务网关
bootstrap.properties
spring.application.name=microservice-gateway
application.properties
server.port=9090
MsGatewayApplication
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class MsGatewayApplication
public static void main(String[] args)
SpringApplication.run(MsGatewayApplication.class, args);
注意在这个microservice-gateway 项目中,您的类路径必须具有 Ribbon 依赖项。
要运行第二个微服务实例,请使用以下命令:
java -jar -Dserver.port=8082 -Deureka.instance.metadataMap.instanceId=INSTANCE2 microservice-0.0.1-SNAPSHOT.jar
当您点击此网址 http://localhost:9090/microservice/ 时,您将交替收到响应:端口上的微服务:8081,端口上的微服务:8082(这意味着 Ribbon 使用循环算法调用这两个实例)
【讨论】:
他的问题中没有任何内容表明他正在使用 Eureka;事实上,他明确禁用了它ribbon.eureka.enabled=false
尽管他禁用了它,但 pegasus 仍试图解释循环行为。这就是问题所在。【参考方案3】:
如果我没记错的话,“您希望其中一个接收每个请求”,您为什么不使用 Zuul 过滤器(预过滤器)来处理这个问题。对于上述答案,我还想澄清一件事
Please check this link for detail
【讨论】:
以上是关于负载平衡 (ribbon) 和路由 (zuul) Spring REST API (Spring Data JPA) 请求到同一服务的多个副本的主要内容,如果未能解决你的问题,请参考以下文章