Service Discovery with Eureka in Cloud Foundry
A typical cloud application consists of different services that communicate with each other. Because of the cloud’s nature servers come and go and therefore the location of a service (the IP address) will change. Service Discovery allows services to know each other. One way is to set up a service registry where every service can register. Other services can look up the service registry information, get the location and are able to connect to this service directly. A possible implementation of a service registry is Eureka from Netflix.
Spring Boot makes it easy to create stand-alone Spring based applications and with Spring Cloud Netflix it provides an integration of Netflix OSS. In the following I will show a simple setup of a Eureka server with a client in Pivotal Cloud Foundry.
Eureka server
It is really easy to use Eureka with Spring Boot. The first thing you need to start is obviously the server:
- Go to https://start.spring.io/, add Eureka Server to the list of dependencies and generate the project.
- Import the project in your IDE
- Open EurekaApplication.java and add @EnableEurekaServer. It should look like this:
EurekaApplication.javaJava12345678@SpringBootApplication@EnableEurekaServerpublic class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}} - Add the following lines to application.yml to configure the server: (I prefer YAML, but it is also possible to use application.properties which is provided by the project from the Spring Initializer)
application.ymlYAML12345678910server:port: 8761spring:application:name: eurekaeureka:client:registerWithEureka: falsefetchRegistry: false
The properties registerWithEureka: false and fetchRegistry: false prevent that the application acts as a Eureka client and server at the same time.
Eureka client
The next step is to create an application that registers with the service registry. Go to https://start.spring.io/ and create another application. This time add Eureka Discovery as a dependency:
After importing the project in your IDE, add @EnableEurekaClient in the Main class:
1 2 3 4 5 6 7 8 |
@SpringBootApplication @EnableEurekaClient public class TestAppApplication { public static void main(String[] args) { SpringApplication.run(TestAppApplication.class, args); } } |
In application.yml only the application name and the default zone need to be set. The name will be used to register and the defaultZone is the URL of the Eureka server. For a local setup this will be http://127.0.0.1:8761/eureka/.
1 2 3 4 5 6 7 |
spring: application: name: testApp eureka: client: serviceUrl: defaultZone: http://127.0.0.1:8761/eureka/ |
If you start both applications, the logs show that the testApp registers its instance:
Log output of testApp:
1 2 |
DiscoveryClient_TESTAPP/172.16.177.147:testApp: registering service... DiscoveryClient_TESTAPP/172.16.177.147:testApp - registration status: 204 |
Log output of Eureka :
1 |
Registered instance TESTAPP/172.16.177.147:testApp with status UP |
Eureka comes with a built-in web UI where it shows all registered services. Go to http://127.0.0.1:8761 to see the registered instance of testApp:
Now that the local setup is running, let’s take it to the cloud!
Cloud setup
The simplest way to deploy an application to Cloud Foundry is to upload the Jar file directly in Cloud Foundry’s web frontend. But this has some disadvantages. The configuration must be done manually and probably the biggest disadvantage: It is not automated!
To allow automated deployments a manifest file is needed (https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html). If you take a closer look at the manifest.yml of the Eureka server, you see the most relevant property host. This defines that the service will be reachable under eureka-test-service.cfapps.io.
1 2 3 4 5 6 |
--- applications: - name: eureka memory: 512MB host: eureka-test-service path: target/eureka-0.0.1-SNAPSHOT.jar |
To deploy the server to Cloud Foundry we will use the Cloud Foundry CLI. If you have not set up the CLI, you can look it up here: http://docs.cloudfoundry.org/cf-cli/
- First build the jar: mvn clean install
- Then push it to Cloud Foundry: cf push
Congratulations, you have deployed your Eureka server to Cloud Foundry! To verify this, go to http://eureka-test-service.cfapps.io and have a look at the web UI of Eureka.
Adding clients
A service registry without clients is pointless. Therefore the next step is to configure our testApp to use Eureka in the cloud. The easiest way would be to set the default zone to http://eureka-test-service.cfapps.io/eureka/, but this would bind the application to this single instance. If the URL changes you have to recompile the application. Instead of storing environment specific configuration in the application, the environment should provide the URL (see http://12factor.net/config). An easy way to provide the URL via an environment variable is a user provided service.
User provided service
A user provided service (https://docs.cloudfoundry.org/devguide/services/user-provided.html) with the name eureka and the URL of the service registry can be created with the following command:
1 |
cf cups eureka -p '{"url": "http://eureka-test-service.cfapps.io/eureka/"}' |
To enable an application to use a service in Cloud Foundry you have to bind the service to the application.
Cloud profile
If the service is bound to our application it will provide the Eureka URL in the environment variable vcap.services.eureka.credentials.url. To use this in the testApp add a cloud specific spring profile to application.yml and set the defaultZone:
9 10 11 12 13 14 15 16 17 18 |
--- spring: profiles: cloud eureka: instance: nonSecurePort: 80 hostname: ${vcap.application.uris[0]} client: service-url: defaultZone: ${vcap.services.eureka.credentials.url} |
The hostname is set to vcap.application.uris[0]. This variable is provided by Cloud Foundry and contains the public URL of an application. This URL will be used to register with Eureka. Other services can then retrieve this URL from Eureka to connect to testApp.
Manifest
Just as the server project has a manifest.yml, so the testApp will have one:
- The active spring profile is selected with the environment variable spring.profiles.active: cloud which can be set in the env attribute.
- The service eureka is bound to this application in the services block.
The complete manifest.yml should look like this:
1 2 3 4 5 6 7 8 9 10 |
--- applications: - name: testApp memory: 512MB host: testApp-service path: target/testApp-0.0.1-SNAPSHOT.jar env: spring.profiles.active: cloud services: - eureka |
Deploy it to Cloud Foundry
- As usual first build the jar: mvn clean install
- Now push it to Cloud Foundry via CLI: cf push
The logs show the registration of the Eureka client with the Eureka server.
1 2 |
DiscoveryClient_TESTAPP/6b42392c-a1a5-473d-7513-8ff9e53cfc41: registering service... DiscoveryClient_TESTAPP/6b42392c-a1a5-473d-7513-8ff9e53cfc41 - registration status: 204 |
On the UI http://eureka-test-service.cfapps.io you can see that TESTAPP is registered.
That’s it! Within a few simple steps you have created a service registry with Spring Boot. First a Eureka server and client for a local setup, then configured both to be cloud ready and deployed them to Cloud Foundry.
Comment article
Recent posts






Comments
Johannes Dilli
Hi Vinay,
did you set the property “eureka.instance.nonSecurePort” or “eureka.instance.securePort”. In my example, I set “nonSecurePort: 80” to set the default port to 80. With this configuration, the port number should disappear from Eureka. You can find more about this in the official documentation: https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_service_discovery_eureka_clients
Johannes Dilli
Hi Poonam,
thanks for your feedback. I don’t have a blog post about Zuul yet. I can only refer to the official documentary. https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_router_and_filter_zuul
With the default configuration Zuul will fetch the services from Eureka and map the service to an URL, e.g. testApp will be reachable under /testApp. The service name is the name of your application configured via “applications.name”.
I’m sorry I couldn’t give you an exact answer, but I hope the information helps you.
Vinay
Hi, I registered my client in the server. It is showing up too. But it is always appending a port number(8080) with the pcf route for that particular client. Hence it cannot call other clients registered in the same eureka. Without the port number the urls are working perfectly. Any suggestions on how to resolve this.
Vinay
Just check if you are missing /eureka at the end of default zone url. I did the same mistake 😛
Poonam
Hi Johannes,
The post is very useful and i get it done on my machine too.However I got stuck in zuul configurations in cloud.Please refer a post regarding configuring Zuul on Cloud foundry.’
Specifically How to get the service id of services registered in Eureka
sajal jain
I am following the same procedure to deploy Eureka server and Eureka client on PCF cloud. My eureka server has been successfully deployed but when i push eureka client it fails with the error “Could not find service eureka to bind to testApp “. i am not able understand why ?
Can someone please help?
Johannes Dilli
Our defaultZones are different: You added /eureka.
How did you create the user provided service? What is the value of vcap.services.eureka.credentials.uri?
If you created the user provided service with ‘http://eureka-test-service.cfapps.io/eureka/’, your defaultZone will be ‘http://eureka-test-service.cfapps.io/eureka/eureka’ and that will cause an error.
John
Are my .yml files correct?
EUREKA SERVER
————————
=>bootstrap.yml
—
spring:
profiles: cloud
=>application.yml
server:
port: ${vcap.application.port:8761}
spring:
application:
name: eureka
eureka:
client:
registerWithEureka: false
fetchRegistry: false
—————————————
TEST SERVICE
=>bootstrap.yml
—
spring:
profiles: cloud
eureka:
client:
service-url:
defaultZone: ${vcap.services.eureka.credentials.uri}/eureka
=>application.yml
spring:
application:
name: test
eureka:
instance:
nonSecurePort: 80
hostname: ${vcap.application.uris[0]}
John
When I issue ‘cf running-security-groups’ I see both dns & public_network and both show the same info as shown in the help doc. Should there be any additional steps/info?
Johannes Dilli
Hi John,
peer awareness with Eureka in Cloud Foundry is a little bit more complicated. This might be the topic of another blog post.
A simple solution is to add different spring profiles (and different routes for both Eureka servers) like in the Spring Cloud Netflix documentation: http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#_peer_awareness
Johannes Dilli
If the application is not able to reach the Eureka service, you should add a application security group. In my test setup I have the security groups Public Network and DNS from the documentation: https://docs.pivotal.io/pivotalcf/1-7/adminguide/app-sec-groups.html#typical-groups
John
I’m getting a ClientHandlerException: java.net.ConnectException: Connection refused when the client attempts to contact eureka on CF. Should I be creating an application security group?
John
Oh I see. Thanks!
How would the application.yml look for Eureka if you were to set it up for peer to peer for Cloud Foundry
Johannes Dilli
In the cloud setup application.yml I extend the application.yml from the local setup. The first defaultZone is used with the default profile and the second with the cloud profile. So you are still able to run and test the application on your local computer. If you prefer to remove the defaultZone http://127.0.0.1:8761/eureka/, local testing becomes more difficult.
John
In the cloud setup application.yml you have defaulZone twice http://127.0.0.1:8761/eureka/ being the first one. Shouldn’t this be removed, and only contain the following?
spring:
application:
name: testApp
—
spring:
profiles: cloud
eureka:
instance:
nonSecurePort: 80
hostname: ${vcap.application.uris[0]}
client:
service-url:
defaultZone: ${vcap.services.eureka.credentials.url}
Getting Started: Pivotal Spring Tool Suite deployments to local and public CloudFoundry - NovaTec Blog
[…] NovaTec Blog Post by Johannes Dilli: Service discovery with Eureka in Cloud Foundry […]
Getting Started: Pivotal Spring Tool Suite deployments to local and public CloudFoundry - NovaTec Blog
[…] NovaTec Blog Post by Johannes Dilli: Service discovery with Eureka in Cloud Foundry […]