Spring boot 2 + feign + eureka client не будет преобразовывать имя службы в URL

Я пытаюсь выполнить spring -boot (2.0.5) с помощью spring-cloud (Finchley.SR1) и пытаюсь настроить связь между двумя службами, используя Eureka в качестве сервера обнаружения и Feign / Ribbon в качестве клиентов. Настройка довольно проста (хотя немного запутана различными вещами и другими ответами, которые я пробовал):

application.yml от Эврики

spring:
  application:
    name: eureka-service
server:
  port: 8761
eureka:
  instance:
    hostname: localhost
    preferIpAddress: true
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka

bootstrap.yml второй службы

spring:
  application:
    name: secondservice
eureka:
  instance:
    hostname: ${spring.application.name}
    preferIpAddress: true
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
    statusPageUrlPath: ${server.servlet.context-path}/actuator/info
    healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
    leaseRenewalIntervalInSeconds: 15
    leaseExpirationDurationInSeconds: 45
    metadata-map:
      server.servlet.context-path: ${server.servlet.context-path}
  client:
    enabled: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

мой тестовый / шаблонный сервис bootstrap.yml

spring:
  application:
    name: templateservice
eureka:
  instance:
    hostname: ${spring.application.name}
    preferIpAddress: true
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
    statusPageUrlPath: ${server.servlet.context-path}/actuator/info
    healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
    leaseRenewalIntervalInSeconds: 15
    leaseExpirationDurationInSeconds: 45
    metadata-map:
      server.servlet.context-path: ${server.servlet.context-path}
  client:
    enabled: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka
logging:
  level:
    com...MessageServiceClient: DEBUG

Мой фальшивый клиент

@FeignClient(name = "secondservice", configuration = FeignConfig.class)
public interface MessageServiceClient {
    @RequestMapping(method = RequestMethod.GET, value = "/dummy")
    public String getMessage();
}

Мой класс обслуживания:

@Autowired MessageServiceClient messageServiceClient;
@Autowired private LoadBalancerClient loadBalancer;
public String getDummyMessage() {
    ServiceInstance instance = loadBalancer.choose("secondservice");
    URI secondServiceUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));

    System.out.println(secondServiceUri); // logs http://192.168.0.205:8090, check log below

    return messageServiceClient.getMessage(); // throws 404??
}

В FeignConfig единственное, что нужно сделать, - это установить для уровня журнала значение ПОЛНЫЙ. Журнал выглядит так:

2018-10-08 11:14:59.511  INFO [templateservice,,,] 16801 --- [onPool-worker-2] s.c.a.AnnotationConfigApplicationContext : Refreshing SpringClientFactory-secondservice: startup date [Mon Oct 08 11:14:59 IST 2018]; parent: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@451f35ad
2018-10-08 11:14:59.683  INFO [templateservice,,,] 16801 --- [onPool-worker-2] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2018-10-08 11:15:00.042  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:00.095  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.u.concurrent.ShutdownEnabledTimer    : Shutdown hook installed for: NFLoadBalancer-PingTimer-secondservice
2018-10-08 11:15:00.146  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.loadbalancer.BaseLoadBalancer  : Client: secondservice instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=secondservice,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2018-10-08 11:15:00.189  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.l.DynamicServerListLoadBalancer      : Using serverListUpdater PollingServerListUpdater
2018-10-08 11:15:00.287  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:00.291  INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client secondservice initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=secondservice,current list of Servers=[192.168.0.205:8090, 192.168.0.205:8090],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:2;   Active connections count: 0;    Circuit breaker tripped count: 0;   Active connections per server: 0.0;]
},Server stats: [[Server:192.168.0.205:8090;    Zone:defaultZone;   Total Requests:0;   Successive connection failure:0;    Total blackout seconds:0;   Last connection made:Thu Jan 01 05:30:00 IST 1970;  First connection made: Thu Jan 01 05:30:00 IST 1970;    Active Connections:0;   total failure count in last (1000) msecs:0; average resp time:0.0;  90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;  max resp time:0.0;  stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@3625959e
http://192.168.0.205:8090
2018-10-08 11:15:01.215  INFO [templateservice,,,] 16801 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:07.951 DEBUG [templateservice,,,] 16801 --- [onPool-worker-2] c.e.m.t.clients.MessageServiceClient     : [MessageServiceClient#getMessage] ---> GET http://secondservice/dummy HTTP/1.1
2018-10-08 11:15:12.527 DEBUG [templateservice,,,] 16801 --- [onPool-worker-2] c.e.m.t.clients.MessageServiceClient     : [MessageServiceClient#getMessage] <--- HTTP/1.1 404 (4575ms)
2018-10-08 11:15:12.559 ERROR [templateservice,7004692c56b2e643,7004692c56b2e643,false] 16801 --- [nio-8080-exec-4] o.s.c.s.i.web.ExceptionLoggingFilter     : Uncaught exception thrown

Проблема в том, что это выдает 404, конечно, потому что URL-адрес, который он пытается поразить, - http://secondservice/dummy, а такого нет. Возможно, стоит отметить, что если я установлю url в FeignClient, он будет работать, но в чем тогда смысл Eureka? Кроме того, если это работает, будут ли клиенты автоматически использовать контекстный путь? или я должен указывать это в каждом URL-адресе клиента?

ОБНОВЛЕНИЕ 1: ответ на: http://localhost:8761/eureka/apps/secondservice  Ответ от Eureka на второй сервис


person NikhilWanpal    schedule 08.10.2018    source источник
comment
Что будет на выходе, когда вы нажмете: localhost: 8761 / eureka / apps / secondservice   -  person hideburn    schedule 08.10.2018
comment
@hideburn обновил вопрос скриншотом ответа.   -  person NikhilWanpal    schedule 08.10.2018
comment
Хорошо, проверьте следующее: 1. Главный класс вашей службы шаблонов аннотирован @EnableFeignClients. 2. Зависимости вашей службы шаблонов: feign-tape, feign-core, feign-slf4j, tape-loadbalancer.   -  person hideburn    schedule 09.10.2018
comment
Спасибо. Проверил: присутствует аннотация, feign-core, feign-slf4j, tape-loadbalancer. Я могу найти openfeign и ленточные банки на пути, но нет jar / package под названием feign-tape, если вы это имели в виду. лента-сердечник, лента, лента-httpclient и т. д. присутствуют и вытягиваются также как зависимость от симуляции.   -  person NikhilWanpal    schedule 09.10.2018
comment
Добавьте также это: mvnrepository.com/artifact/com.netflix .feign / feign-tape /   -  person hideburn    schedule 09.10.2018
comment
добавлено (в обеих службах) по-прежнему нет изменений в поведении. все еще говорится: GET http://secondservice/dummy HTTP/1.1   -  person NikhilWanpal    schedule 09.10.2018


Ответы (2)


Нашел! Это не имеет ничего общего с обнаружением или конфигурацией в целом, это потому, что feign не поддерживает контекстный путь!

Пытаясь «немыть», я удалил каждую конфигурацию до минимума, чтобы службы продолжали работать. Это внезапно сработало, когда я удалил контекстный путь второй службы. Дело в том, что Feign + Ribbon не поддерживает настраиваемый контекстный путь, если он задан другой службой. Это старая ошибка, которая до сих пор не исправлена.

Есть два возможных решения:

  1. Удалить контекстный путь.
  2. Добавьте контекстный путь в своих клиентах Feign. Итак, в основном ваш клиент Feign становится:

// Это должно быть здесь, чтобы форматирование ниже было правильным

@FeignClient(name = "secondservice/secondservice", configuration = FeignConfig.class)
public interface MessageServiceClient {
    @RequestMapping(method = RequestMethod.GET, value = "/dummy")
    public String getMessage();
}

Мне лично не нравится ни одно из решений. Мне нравится иметь контекстный путь, ну, чтобы дать контекст URL-адресу, он становится понятным с контекстом. Но это свойство другой службы (второй службы) и должно быть выбрано / изменено этой службой. И поэтому не следует жестко закодировать зависимые службы. Я бы хотел, чтобы его поддержали, но пока я собираюсь пойти на:

@FeignClient(name = "${dependencies.secondservice.url}")
public interface MessageServiceClient {....}

И в application.properties: dependencies.secondservice.url=secondservice/secondservice. Это дает понять, что свойство принадлежит зависимости, а не этой службе.

Еще несколько примечаний: 1. Я смог отследить запрос до SynchronousMethodHandler#executeAndDecode, response = client.execute(request, options);. До сих пор примечание разрешено. 2. Регистрируемый URL-адрес: GET http://secondservice/secondservice/dummy на самом деле является правильным URL-адресом, первая строка secondservice заменяется на IP после оператора журнала. Вот документация, подтверждающая это: https://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_using_ribbon. Обратите внимание на URL-адрес, переданный в restTemplate. Это послужило толчком к поиску альтернативных причин.

person NikhilWanpal    schedule 09.10.2018

Я меняю значение eureka.client.serviceUrl.defaultZone из файла свойств обоих сервисов. Затем я заменил localhost на IP-адрес, и у меня это сработало.

Надеюсь, это поможет?

person Amey Joshi    schedule 07.10.2019