负载平衡 (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) 请求到同一服务的多个副本的主要内容,如果未能解决你的问题,请参考以下文章

Springcloud zuul 路由配置规则

第四篇:路由网关(zuul)

Zuul 路由网关

SpringCloud路由网关Zuul

Spring Cloud微服务Ribbon负载均衡/Zuul网关使用

Zuul 和 Ribbon 集成