2

我正在一个微服务架构中工作,其工作方式如下

在此处输入图像描述

我有两个服务 Web 应用程序(REST 服务)在 eureka 服务器中正确注册自己,然后我有一个客户端应用程序获取 eureka 注册表并使用功能区作为客户端负载均衡器,确定​​哪个服务应用程序去(目前,正在使用一个简单的循环)。

我的问题是,当我停止其中一个服务应用程序(它们当前在 docker 容器中运行)时,eureka 不会将它们从注册表中删除(似乎需要几分钟),所以功能区仍然认为有 2 个可用服务,使得大约 50% 的呼叫失败。

不幸的是,我没有使用 Spring Cloud(我无法控制的原因)。所以我对尤里卡的配置如下。

对于服务应用程序:

eureka.registration.enabled=true
eureka.name=skeleton-service
eureka.vipAddress=skeleton-service
eureka.statusPageUrlPath=/health/ping
eureka.healthCheckUrlPath=/health/check

eureka.port.enabled=8042
eureka.port=8042

eureka.appinfo.replicate.interval=5

## configuration related to reaching the eureka servers
eureka.preferSameZone=true
eureka.shouldUseDns=false
eureka.serviceUrl.default=http://eureka-container:8080/eureka/v2/

eureka.decoderName=JacksonJson

对于客户端应用程序(eureka + 功能区)

###Eureka Client configuration for Sample Eureka Client


eureka.registration.enabled=false 
eureka.name=skeleton-web
eureka.vipAddress=skeleton-web
eureka.statusPageUrlPath=/health/ping
eureka.healthCheckUrlPath=/health/check

eureka.port.enabled=8043
eureka.port=8043

## configuration related to reaching the eureka servers
eureka.preferSameZone=true
eureka.shouldUseDns=false
eureka.serviceUrl.default=http://eureka-container:8080/eureka/v2/

eureka.decoderName=JacksonJson

eureka.renewalThresholdUpdateIntervalMs=3000


#####################
# RIBBON STUFF HERE #
#####################

sample-client.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList

# expressed in milliseconds
sample-client.ribbon.ServerListRefreshInterval=3000

# movieservice is the virtual address that the target server(s) uses to register with Eureka server
sample-client.ribbon.DeploymentContextBasedVipAddresses=skeleton-service
4

1 回答 1

0

我在开发过程中遇到过类似的问题,我尝试过很多事情并为我工作过。

1)不使用eureka注册表,只使用底层功能区并根据我们的需要修改它的健康检查机制,为此提供自己的IPing实现

public class PingUrl implements com.netflix.loadbalancer.IPing {

public boolean isAlive(Server server) {
        String urlStr = "";
        if (isSecure) {
            urlStr = "https://";
        } else {
            urlStr = "http://";
        }
        urlStr += server.getId();
        urlStr += getPingAppendString();

        boolean isAlive = false;
        try {
            ResponseEntity response = getRestTemplate().getForEntity(urlStr, String.class);
            isAlive = (response.getStatusCode().value()==200);

        } catch (Exception e) {
            ;
        }
        return isAlive;
    }
}

覆盖负载平衡行为

@SpringBootApplication
@EnableZuulProxy
@RibbonClients(defaultConfiguration = LoadBalancer.class)
@ComponentScan(basePackages = {"com.test"})
public class APIGateway {   

    public static void main(String[] args) throws Exception {
        SpringApplication.run(APIGateway .class, args);
    }

}

    public class LoadBalancer{

    @Autowired
        IClientConfig ribbonClientConfig;

    @Bean
        public IPing ribbonPing() {

            return new PingUrl(getRoute() + "/ping");
        }
    }

  private String getRoute() {
        return RequestContext.getCurrentContext().getRequest().getServletPath();
}

提供可用性过滤规则

public class AvailabilityBasedServerSelectionRule extends AvailabilityFilteringRule {

    @Override
    public Server choose(Object key) {

        Server chosenServer = super.choose(key);

        int count = 1;
        List<Server> reachableServers = this.getLoadBalancer().getReachableServers();
        List<Server> allServers = this.getLoadBalancer().getAllServers();

        if(reachableServers.size() > 0) {
            while(!reachableServers.contains(chosenServer) && count++ < allServers.size()) {
                chosenServer = reachableServers.get(0);
            }
        }
        return chosenServer;
    }

2)可以指定刷新列表的时间间隔

ribbon.eureka.ServerListRefreshInterval={time in ms}
于 2018-10-31T06:20:15.397 回答