最近我一直在做一个 API 网关项目。然而,对于服务注册和发现,我遇到了一些关于 Zuul 故障转移和动态部署多个 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);
}
}
配置:应用程序.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
我将 peer1 和 peer2 配置为主机中的 localhost
zuul 带丝带项目
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;
}
}
预过滤器: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/
源代码结束,附件是源代码
我通过更改活动启动了2个eureka实例,然后启动了zuul服务器。最后,我通过更改服务器端口启动了 2 个目标服务。我使用 JMeter 进行了一些测试。我在并发测试中停止了一个目标服务,然后一些请求失败了关于socket closed。
所以问题是为什么 zuul 和ribbon 无法处理故障转移,或者我应该如何配置才能达到这种效果?
第二个问题是每次部署另一个eureka server时,需要编辑eureka server配置、zuul配置和目标服务配置。因此,所有这些项目都需要重新启动。我不能接受,那么有没有办法在不编辑其他项目的配置并重新启动它们的情况下动态更改 eureka 服务器的数量?
最后,我希望 Pivotal 团队可以更新 Spring Cloud 的文档以提供更详细的信息。