最近我一直在做一个API网关项目。但是,对于服务注册和发现,我遇到了一些关于Zuul故障转移和动态部署多个Eureka实例的问题。以下是我的项目。
eureka server project
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);
}
}
配置: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
我在host
中将peer1和peer2配置为localhostzuul with ribbon project
ZuulBootstrap.java
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;
}
}
PreFilter: SimpleFilter.java
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配置:application.yml
#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/
源码结束,附件是源码
我通过更改active启动了2个eureka实例,然后启动了zuul服务器。最后,我通过更改服务器端口启动了2个目标服务。我用JMeter做了一些测试。我在并发测试中停止了一个目标服务,然后关于socket关闭的一些请求失败。
所以问题是为什么zuul和ribbon不能处理故障转移或者我应该如何配置以达到这种效果?
第二个问题是每次我部署另一个eureka服务器时,我都需要编辑eureka服务器配置、zuul配置和目标服务配置。因此,所有这些项目都需要重新启动。我不能接受,所以有没有一种方法可以动态地改变尤里卡服务器的数量而不编辑其他项目的配置并重新启动它们?
最后,我希望Pivotal团队能够更新spring cloud的文档,提供更详细的信息。
您必须为所有客户端应用程序提供如下所有实例(逗号分隔列表)-bootstrap.properties -eureka.client.serviceUrl.defaultZone = http://localhost: 8761/尤里卡,http://localhost: 8762/尤里卡
因为如果你只让eureka服务器意识到彼此,那么它们可以复制所有的实例,这是一个完美的部分。现在假设在客户端应用中,如果你只传递一个实例eureka.client.serviceUrl.defaultZone = http://localhost: 8761/尤里卡假设这个应用程序将重新启动,而此时这个eureka实例关闭了那么在这种情况下,它会检查另一个eureka服务器实例,而不是你在客户端应用程序中只提供了一个实例。
因此,你必须在客户端应用程序中提供eureka服务器的所有实例。由于