Spring Cloud Config Eureka-first approach not working

chrx picture chrx · Feb 3, 2016 · Viewed 16.2k times · Source

I'm developing a Spring Cloud Eureka microservices application. I want my services to connect to the config service via an Eureka-first approach. Microservices are packaged as docker containers and deployed via docker-compose. The application is composed by:

  1. myapp-service-registry: a service registry service implemented with Spring Cloud Eureka
  2. myapp-config-service: a Spring Cloud config service server
  3. myapp-service-test: An example microservice which should try to take its config data from the config service by connecting to this via an Eureka-first approach.

The connection to the config service fail as described below. First of all some configuration data:

Here is myapp-service-registry's application.yml:

server:
  port: ${PORT:8761}

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0

Here the myapp-config-service's application.yml:

server:
  port: ${MYAPP_CONFIG_SERVICE_PORT:8888}

spring: 
  cloud:
    config:
      server:
        git:
          uri: ${MYAPP_CONFIG_SERVICE_GIT_URI}
  config:
    name: myapp-config-service

# eureka service registry client

eureka: 
    client:
        serviceUrl:
            defaultZone: http://${SERVICE_REGISTRY_HOST}:${SERVICE_REGISTRY_PORT}/eureka/
    instance:
        preferIpAddress: true

Config server and client are initialized as in configserver-eureka and eureka-first samples in https://github.com/spring-cloud-samples/tests :

myapp-config-service's bootstrap.yml is:

spring:
    application:
        name: myapp-config-service
    cloud:
        config:
            discovery:
                enabled: true

And myapp-service-test's application.yml:

eureka:
    client:
        serviceUrl:
            defaultZone: http://${SERVICE_REGISTRY_HOST}:${SERVICE_REGISTRY_PORT}/eureka/
    instance:
        preferIpAddress: true

And myapp-service-test's bootstrap.yml:

spring:
  application:
    name: myapp-service-test
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: myapp-config-service

Following is the docker-compose.yml (env variable are replaced with actual values at launch):

myapp-service-registry:
image: myapp/myapp-service-registry:0.0.1
ports:
    - ${EUREKA_PORT}:${EUREKA_PORT}

# myapp-config-service

myapp-config-service:
    image: myapp/myapp-config-service:0.0.1
    volumes:
    - ${MYAPP_DATA_FOLDER}/config:/var/opt/myapp/config
    environment:
      MYAPP_CONFIG_SERVICE_PORT: ${MYAPP_CONFIG_SERVICE_PORT}
      SERVICE_REGISTRY_HOST: ${MYAPP_STAGING_IP}
      SERVICE_REGISTRY_PORT: ${EUREKA_PORT}
      MYAPP_CONFIG_SERVICE_GIT_URI: ${MYAPP_CONFIG_SERVICE_GIT_URI}
    ports:
        - ${MYAPP_CONFIG_SERVICE_PORT}:${MYAPP_CONFIG_SERVICE_PORT}

 # myapp-service-test

myapp-service-test:
  image: myapp/myapp-service-test:0.0.1
  environment:
    SERVICE_REGISTRY_HOST: ${MYAPP_STAGING_IP}
    SERVICE_REGISTRY_PORT: ${EUREKA_PORT}
  ports:
    - ${MYAPP_SERVICE_TEST_TWO_PORT}:8080

I can check that Eureka is working by connecting the browser to http://[...MACHINE-IP...]:8761/ and seeing the Eureka dashboard. Similarly, I test that the config service is working and responds to http:///[...MACHINE-IP...]:8888/myapp-config-service; With the above configuration, on the other hand, myapp-service-test crashes at startup with the following log:

-02-03 08:26:45.191  INFO 1 --- [           main] e.f.s.two.TestServiceApplication      : Starting TestServiceApplication v0.0.1 on b1bc37422027 with PID 1 (/app.jar started by root in /)
2016-02-03 08:26:45.223  INFO 1 --- [           main] e.f.s.two.TestServiceApplication      : No active profile set, falling back to default profiles: default
2016-02-03 08:26:45.448  INFO 1 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4d97e82d: startup date [Wed Feb 03 08:26:45 UTC 2016]; root of context hierarchy
2016-02-03 08:26:46.382  INFO 1 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2016-02-03 08:26:46.442  INFO 1 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$6b65138e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2016-02-03 08:26:47.089  INFO 1 --- [           main] o.s.c.n.eureka.InstanceInfoFactory       : Setting initial instance status as: STARTING
2016-02-03 08:26:48.231  INFO 1 --- [           main] c.n.d.provider.DiscoveryJerseyProvider   : Using encoding codec LegacyJacksonJson
2016-02-03 08:26:48.237  INFO 1 --- [           main] c.n.d.provider.DiscoveryJerseyProvider   : Using decoding codec LegacyJacksonJson
2016-02-03 08:26:49.171  INFO 1 --- [           main] c.n.d.provider.DiscoveryJerseyProvider   : Using encoding codec LegacyJacksonJson
2016-02-03 08:26:49.171  INFO 1 --- [           main] c.n.d.provider.DiscoveryJerseyProvider   : Using decoding codec LegacyJacksonJson
2016-02-03 08:26:49.496  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Disable delta property : false
2016-02-03 08:26:49.497  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Single vip registry refresh property : null
2016-02-03 08:26:49.497  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Force full registry fetch : false
2016-02-03 08:26:49.498  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Application is null : false
2016-02-03 08:26:49.502  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Registered Applications size is zero : true
2016-02-03 08:26:49.503  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Application version is -1: true
2016-02-03 08:26:49.503  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Getting all instance registry info from the eureka server
2016-02-03 08:26:49.720  WARN 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Can't get a response from http://localhost:8761/eureka/apps/
<...>
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
    at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:187) ~[jersey-apache-client4-1.19.jar!/:1.19]
    at com.sun.jersey.api.client.filter.GZIPContentEncodingFilter.handle(GZIPContentEncodingFilter.java:123) ~[jersey-client-1.19.jar!/:1.19]
    at com.netflix.discovery.EurekaIdentityHeaderFilter.handle(EurekaIdentityHeaderFilter.java:27) ~[eureka-client-1.3.4.jar!/:1.3.4]
    <...>
Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_66-internal]
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_66-internal]
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_66-internal]
    <...>

2016-02-03 08:26:49.747 ERROR 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Can't contact any eureka nodes - possibly a security group issue?

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
    <...>

2016-02-03 08:26:49.770 ERROR 1 --- [           main] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_MYAPP-SERVICE-TEST/b1bc37422027:myapp-service-test - was unable to refresh its cache! status = java.net.ConnectException: Connection refused

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
    <...>

2016-02-03 08:26:49.785  WARN 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Using default backup registry implementation which does not do anything.
2016-02-03 08:26:49.810  INFO 1 --- [           main] com.netflix.discovery.DiscoveryClient    : Starting heartbeat executor: renew interval is: 10
2016-02-03 08:26:49.818  INFO 1 --- [           main] c.n.discovery.InstanceInfoReplicator     : InstanceInfoReplicator onDemand update allowed rate per min is 4
2016-02-03 08:26:50.443  WARN 1 --- [           main] lientConfigServiceBootstrapConfiguration : Could not locate configserver via discovery

java.lang.RuntimeException: No matches for the virtual host name :myapp-config-service
    at com.netflix.discovery.DiscoveryClient.getNextServerFromEureka(DiscoveryClient.java:782) ~[eureka-client-1.3.4.jar!/:1.3.4]
    at org.springframework.cloud.netflix.config.DiscoveryClientConfigServiceBootstrapConfiguration.refresh(DiscoveryClientConfigServiceBootstrapConfiguration.java:71) [spring-cloud-netflix-core-1.1.0.M3.jar!/:1.1.0.M3]
    <...>

2016-02-03 08:26:50.470  INFO 1 --- [           main] e.f.s.two.TestServiceApplication      : Started TestServiceApplication in 7.101 seconds (JVM running for 9.329)

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.1.RELEASE)

2016-02-03 08:26:50.773  INFO 1 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2016-02-03 08:26:51.015  WARN 1 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/myapp-service-test/default":Connection refused; nested exception is java.net.ConnectException: Connection refused

<...>

2016-02-03 08:26:54.856 ERROR 1 --- [pool-5-thread-1] com.netflix.discovery.DiscoveryClient    : Can't contact any eureka nodes - possibly a security group issue?

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
    <...>

2016-02-03 08:26:57.272  WARN 1 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testTwoServiceController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: java.lang.String myapp.services.two.TestServiceController.message; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'message' in string value "${message}"
2016-02-03 08:26:57.281  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat
2016-02-03 08:26:57.299 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application startup failed

Note that if I don't implement an Eureka-first approach (and set spring.cloud.config.uri directly in the service's bootstrap.yml), the service registers to Eureka, finds the config server and works correctly (I can see the registered service in Eureka's dashboard and can check that config properties are correctly read).

Answer

Dave Syer picture Dave Syer · Feb 3, 2016

You need the eureka serviceUrl in the bootstrap.yml (as well as the service id of the configserver).