Spring cloud spring cloud zuul使用eureka进行故障切换,并动态部署多个eureka实例

Spring cloud spring cloud zuul使用eureka进行故障切换,并动态部署多个eureka实例,spring-cloud,netflix-zuul,netflix-eureka,netflix-ribbon,Spring Cloud,Netflix Zuul,Netflix Eureka,Netflix Ribbon,最近我一直在做一个API网关项目。但是,对于service registry和discovery,我遇到了一些关于Zuul故障切换和动态部署多个Eureka实例的问题。以下是我的项目 eureka服务器项目 EurekaBootstrap.java package com.plateno.cloud.netflix.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.

最近我一直在做一个API网关项目。但是,对于service registry和discovery,我遇到了一些关于Zuul故障切换和动态部署多个Eureka实例的问题。以下是我的项目

eureka服务器项目

EurekaBootstrap.java

package com.plateno.cloud.netflix.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaBootstrap {
public static void main(String[] args) {
    SpringApplication.run(EurekaBootstrap.class, args);
 }
}
package com.plateno.cloud.netflix.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.PatternServiceRouteMapper;
import org.springframework.context.annotation.Bean;

import com.netflix.zuul.exception.ZuulException;

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

    @Bean
    public SimpleFilter simpleFilter() {
        return new SimpleFilter();
    }

    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper("(?<name>^.+)", "${name}") {
            @Override
            public String apply(final String serviceId) {
                String route = super.apply(serviceId);
                return route;
            }
        };
    }

    @RefreshScope
    @ConfigurationProperties("zuul")
    public ZuulProperties zuulProperties() {
        ZuulProperties zuulProperties = new ZuulProperties();
        return zuulProperties;
    }
}
package com.plateno.cloud.netflix.zuul;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class SimpleFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        return null;
    }
}
config:application.yml

#spring.application.name=plateno-cloud-netflix-eureka
#server.port=9000
#eureka.instance.hostname=localhost
#eureka.client.registerWithEureka=false
#eureka.client.fetchRegistry=false
#eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#spring.profiles.active: dev

server:
    port: 9000
spring.application.name: localhost
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:${server.port}/eureka/
  instance:
    hostname: localhost
eureka.client.register-with-eureka: false
eureka.client.fetch-registry: false
---
spring:
    profiles: peer1
server:
    port: 9001
peer2:
    port: 9002    
spring.application.name: peer1
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer2:${peer2.port}/eureka/  
  instance:
    hostname: peer1
eureka.client.register-with-eureka: true
eureka.client.fetch-registry: true
---
spring:
    profiles: peer2
server:
    port: 9002
spring.application.name: peer2
peer1:
    port: 9001 
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:${peer1.port}/eureka/
  instance:
    hostname: peer2
eureka.client.register-with-eureka: true
eureka.client.fetch-registry: true
---
spring:
  profiles:
    active: peer1
#default_charset=utf-8
#spring.application.name=plateno-cloud-netflix-zuul
#server.port=9030
#ribbon.eureka.enabled=true
#eureka.client.serviceUrl.defaultZone=http\://localhost\:9001/eureka/

---
default_charset: utf-8
spring:
  application:
    name: plateno-cloud-netflix-zuul
server:
  port: 9030
ribbon: 
  eureka:
    enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
我将peer1和peer2配置为主机中的本地主机

zuul带丝带项目

ZuulBootstrap.java

package com.plateno.cloud.netflix.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaBootstrap {
public static void main(String[] args) {
    SpringApplication.run(EurekaBootstrap.class, args);
 }
}
package com.plateno.cloud.netflix.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.PatternServiceRouteMapper;
import org.springframework.context.annotation.Bean;

import com.netflix.zuul.exception.ZuulException;

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

    @Bean
    public SimpleFilter simpleFilter() {
        return new SimpleFilter();
    }

    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper("(?<name>^.+)", "${name}") {
            @Override
            public String apply(final String serviceId) {
                String route = super.apply(serviceId);
                return route;
            }
        };
    }

    @RefreshScope
    @ConfigurationProperties("zuul")
    public ZuulProperties zuulProperties() {
        ZuulProperties zuulProperties = new ZuulProperties();
        return zuulProperties;
    }
}
package com.plateno.cloud.netflix.zuul;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class SimpleFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        return null;
    }
}
zuul-config:application.yml

#spring.application.name=plateno-cloud-netflix-eureka
#server.port=9000
#eureka.instance.hostname=localhost
#eureka.client.registerWithEureka=false
#eureka.client.fetchRegistry=false
#eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#spring.profiles.active: dev

server:
    port: 9000
spring.application.name: localhost
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:${server.port}/eureka/
  instance:
    hostname: localhost
eureka.client.register-with-eureka: false
eureka.client.fetch-registry: false
---
spring:
    profiles: peer1
server:
    port: 9001
peer2:
    port: 9002    
spring.application.name: peer1
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer2:${peer2.port}/eureka/  
  instance:
    hostname: peer1
eureka.client.register-with-eureka: true
eureka.client.fetch-registry: true
---
spring:
    profiles: peer2
server:
    port: 9002
spring.application.name: peer2
peer1:
    port: 9001 
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:${peer1.port}/eureka/
  instance:
    hostname: peer2
eureka.client.register-with-eureka: true
eureka.client.fetch-registry: true
---
spring:
  profiles:
    active: peer1
#default_charset=utf-8
#spring.application.name=plateno-cloud-netflix-zuul
#server.port=9030
#ribbon.eureka.enabled=true
#eureka.client.serviceUrl.defaultZone=http\://localhost\:9001/eureka/

---
default_charset: utf-8
spring:
  application:
    name: plateno-cloud-netflix-zuul
server:
  port: 9030
ribbon: 
  eureka:
    enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
目标服务项目 仅使用yml配置的普通项目

我没有解析这个项目的源代码,而是配置配置文件

#default_charset=utf-8
#spring.application.name=plateno-app0
#server.port=9010
#eureka.client.serviceUrl.defaultZone=http\://localhost\:9000/eureka/
server:
    port: 8080
default_charset: utf-8
spring:
  application:
    name: plateno-app0

eureka.client.serviceUrl.defaultZone: http://peer1:9001/eureka/,http://peer2:9002/eureka/
结束sourece,附件是源代码

我通过更改active启动了2个eureka实例,然后启动了zuul服务器。最后,我通过更改服务器端口启动了2个目标服务。我使用JMeter运行了一些测试。在一个并发测试的中间,i <强>停止了一个目标服务<强>,然后关于<强>套接字关闭< /强> ./p>的一些请求失败。 所以问题是为什么zuul和ribbon无法处理故障转移,或者我应该如何配置以达到这种效果

第二个问题是,每次部署另一台eureka服务器时,我都需要编辑eureka服务器配置、zuul配置和目标服务配置。因此,所有这些项目都需要重新启动。我不能接受这一点,那么有没有办法在不编辑其他项目的配置并重新启动它们的情况下动态更改eureka server的数量


最后,我希望Pivotal团队能够更新spring cloud的文档以提供更详细的信息。

您必须为所有客户端应用程序提供以下所有实例(逗号速率列表)- bootstrap.properties- eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka

因为如果您只让eureka服务器知道彼此,那么它们可以复制所有实例,这是完美的一部分。 现在假设在客户端应用程序中,如果只传递一个实例- eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka 假设此应用程序将重新启动,此时您的eureka实例已关闭 那么,在这种情况下会发生什么呢?它将检查另一个eureka服务器实例,但如何在客户端应用程序中仅提供一个实例

因此,您必须在客户端应用程序中提供eureka server的所有实例。
感谢

关于“在不编辑其他项目的配置并重新启动它们的情况下动态更改eureka服务器的数量”,答案是否定的。Netflix使用弹性ip和dns作为eureka服务器的基本静态列表。谢谢,我会寻找它