Multiple services on a Hystrix/Turbine dashboard? - spring-boot

I am trying to get a view on 2 different services that are running using Spring Boot. Both services are nicely registered in Eureka and now i want to get some Hystrix data plotted in the Turbine webapplication.
When testing out the single services using Turbine it works great:
http://localhost:2222/hystrix.stream (service1)
http://localhost:3333/hystrix.stream (service2)
I am trying to get a view on the dashboard which plots both of the services but whatever i try only the first service in the Turbine config is plotted.
turbine:
clusterNameExpression: new String('default')
appConfig: service1,service2
I seem to hit a wall when trying to get the data into the turbine.stream for both of the services.
Any hints or tips?

To answer my own question, it seems that Turbine cannot monitor more services on the same host as it is bound to the hostname. See https://github.com/Netflix/Turbine/issues/88
Turbine has 2 operating models:
pull; data from separate service streams are pulled by Turbine
push; data from separate services are pushed to a Turbine server by using an AMQP broker such as RabbitMQ
A workaround is to use TurbineAMQP that is capable of doing exact the stuff that i needed. It involves a bit more infrastructure but works nicely!

First off, I don't think Turbine is host-exclusive as Marco saying
... it seems that Turbine cannot monitor more services on the same host as it is bound to the hostname
I implemented Turbine with the Hystrix Dashboard App (which is not recommended), aggregating 2 services with same spring.application.name.
I found how Turbine collects hystrix stream is that, each Turbine application will look for services in Eureka Registry with the given name by turbine.appConfig in application.properties, which is the spring.application.name by default or eureka.instance.appname explicitly of your services, regardless of the hosts of them. Till now turbine stream is ready.
A list of names as service IDs from your request in the previous step will be returned, and at least one of them should match the list of names you provide in turbine.aggregator.clusterConfig.
When you type http://[turbine-app-host:port]/turbine.stream?cluster=[cluster name] on the home page of Hystrix Dashboard, the cluster name parameter should be one of the matching names from turbine.aggregator.clusterConfig.

Related

How Ribbon retrieves the list of available instances of a service

I am using ribbon as a load balancer on API gateway and eureka server. When a client request comes to my API gateway, does it query the service registry each time to obtain the available instances of a service, or does Ribbon store the available instances into its cache?
Spring Cloud Ribbon talks to discovery client for getting information about running instances of a given service. Discovery client keeps an in-memory cache of eureka registrations, to make lookup faster.
You can have a look at the Spring Cloud Netflix documentation for more information:
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-eureka-server.html
The Eureka server does not have a back end store, but the service instances in the registry all have to send heartbeats to keep their registrations up to date (so this can be done in memory). Clients also have an in-memory cache of Eureka registrations (so they do not have to go to the registry for every request to a service).
Also, for Ribbon with Eureka:
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html#_using_ribbon_with_eureka
When Eureka is used in conjunction with Ribbon (that is, both are on the classpath), the ribbonServerList is overridden with an extension of DiscoveryEnabledNIWSServerList, which populates the list of servers from Eureka.
The clients from any zone can look up the registry information (happens every 30 seconds) to locate their services (which could be in any zone) and make remote calls. Fore more information, please visit Official Netflix Eureka Documentation
I know that ribbon got a scheduled task for each service, and the task will fetching new server list from registry.
you can have look for this:ScheduledThreadPoolExecutor
the default interval for task to run is 30 seconds, and you can change it with the config:
your-service-name:
ribbon:
ServerListRefreshInterval: 200(the time you want to set in ms)

How can I get Host:Port from all Spring Boot Instances registered at a Eureka Server?

I have some spring-boot clients registered at an eureka server and I'd like to write a client that performs actions on all server instances e.g. call the health check.
Therefore I need all IPs and Ports but when I start the spring-boot instance with server.port=0 to be able to start multiple instances for loadbalancing the eureka api returns port 0 for all of the instances
List<String> apps = discoveryClient.getServices();
for (String app : apps ){
List<ServiceInstance> instances = this.discoveryClient.getInstances(app);
for (ServiceInstance instance : instances){
String url = "http://"+ instance.getHost() + ":"+ instance.getPort();
Also the eureka rest api returns the same
http://localhost:40001/eureka/apps
How can I get the correct ports on which the instances are started ?
You need to set eureka.instance.instance-id to something that is unique. By default, that includes the port which means all of you instances have the same instance id.
Ideally you would use something other than ${random.int} that the platform you are using provides you for uniqueness.
eureka:
instance:
instance-id: ${spring.application.name}:${random.int}
I believe the Spring documentation states that port=0 is really only intended for development purposes.
For micro-services (which is what Spring Boot is for), the whole point would be to have things on different servers/containers.
Which means each can have the same port (which is nice later because you can use well defined / common practice ports to remember what is what).
Just set real ports, because that is what you will do for production.
For development, that will still work because stuff will run on
localhost:8000
localhost:8001
localhost:8002
etc
The only case it won't is when you want to spin up 2 stacks at once.
For which you could either use containers (Docker,Vagrant, etc) or you can use Spring Profiles or Environment variables to specify the Spring property at runtime.

Zuul Autodiscovery issues

We are in the process of standing up a new microservices architecture with Zuul at the front-end and a bunch of tomcat enabled microservices at the backend. Each service as it starts up, will register itself with Eureka and any client that wants to call those service will do so through Zuul. We've got this all wired in and everything is working fine.
However, I have a couple questions as to how we can make this architecture much more dynamic.
One thing that we assumed was there out of the box with Ribbon/Eureka, but have yet to find a solution for is that as we add more services to the backend, that somehow (via Archiaus and update to Zuul's eureka-client.properties file) Zuul's Ribbon client would update itself with the new service details (e.g. vipaddress, load balancing algorithm, etc). So far, the only thing that works is to update the properties file and restart Zuul (ughhh).
For example, let's say today we have 2 microservices at the backend, therefore, Zuul's eureka/ribbon client configuration would include the below:
ribbon.client.niws.clientlist=service1|service2
zuul.ribbon.namespace=zuul.client
service1.zuul.client.DeploymentContextBasedVipAddresses=myService1
service1.zuul.client.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
service2.zuul.client.DeploymentContextBasedVipAddresses=myService2
service2.zuul.client.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
Now tomorrow, let's assume we need to add service3. What we have observed is that if we add those details to the same configuration (see below), they only become available to Zuul after a restart. Is there some other configuration parameter we are missing that would allow us to dynamically introduce the new service details or do we have to roll our own Eureka/Ribbon client to do this?
ribbon.client.niws.clientlist=service1|service2|service3
zuul.ribbon.namespace=zuul.client
service1.zuul.client.DeploymentContextBasedVipAddresses=myService1
service1.zuul.client.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
service2.zuul.client.DeploymentContextBasedVipAddresses=myService2
service2.zuul.client.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
service3.zuul.client.DeploymentContextBasedVipAddresses=myService3
service3.zuul.client.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
My other question is related and that is do we really need to add a client configuration (in eureka-client.properties) for every service that Zuul could possibly route to? At some point, we may have 100's of services running and trying to maintain all the related client configurations in Zuul seems a bit clumsy. Is there a way to globally configure Zuul to load all services into its client list from Eureka (or based on some service metadata in Eureka) and dynamically update this list as new services register themselves with Eureka?
Thanks!
The issue is with namespaces.If we use the default namespace it should be able to pick up the new properties addedd by default.

How to configure DS Replicas links in Spring Cloud Eureka Server Dashboard

I setup an Eureka cluster composed of 3 replicas.
I got the nice dashboard which is automatically populated with the instances currently registered with Eureka and the DS Replicas.
However the DS Replicas links seems to point to the value I set as eureka.client.serviceUrl.defaultZone. In my case this value is something similar to http://node-01:8761/eureka/ which in reality returns a 404. Is there a way I could configure the dashboard to strip out the /eureka/ part so when I follow the links I end up in the other dashboards or am I misunderstanding the use of those links?
There is no easy way to alter the link as you ask.
However, the UI part of the Eureka server is a standard Spring MVC #Controller. An instance of it is created by org.springframework.cloud.netflix.eureka.server.EurekaServerConfiguration. Have a look at the current implementation... it shouldn't be too hard to provide your own customized version instead.

Spring Cloud Turbine - Unable to handle multiple clients?

I’m having a bit of trouble getting Turbine to work in Spring Cloud. In a nutshell, I can’t determine how to configure it to aggregate circuits from more than one application at a time.
I have 6 separate services, a eureka server, and a turbine server running in standalone mode. I can see from my Eureka server that all of the services are registered, including turbine. My turbine server is up and running, and I can see its /hystrix page without issue. But when I try to use it to examine turbine.stream, I only see the FIRST server that is listed in turbine.appConfig, the rest are ignored.
This is my Turbine server’s application.yml, or at least the relevant parts:
---
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8010/eureka/
server:
port: 8030
info:
component: Turbine
turbine:
clusterNameExpression: new String(“default”)
appConfig: sentence,subject,verb,article,adjective,noun
management:
port: 8990
When I run this and access the hystrix dashboard on my turbine instance, asking for the turbine.stream, the ONLY circuit breakers listed in the output are for the first service listed in appConfig, the “sentence” service in this case. Curiously, if I re-arrange the order of these services and put another one first (like “noun”), I see only the circuits for THAT service. Only the first service in the list is displayed.
I’ll admit to being a little confused on some of the terminology, like streams, clusters, etc., so I could be missing some basic concept here, but my understanding is that Turbine could digest streams from more than one service and aggregate them in a single display. Suggestions would be appreciated.
I don't have enough reputation to comment, so I have to write this in an answer :)
I had the exactly same problem:
There are two services "test-service" and "other-service", each with it's own working hystrix-stream
and there is one Turbine-Application, which is configured like this:
turbine:
clusterNameExpression: new String("default")
appConfig: test-service,other-service
All of my services are running on my local machine.
Result is: My Hystrix-Dashboard just shows the metrics from "test-service".
Reason:
It seems to be, that a Turbine-Client which is configured the described way doesn't handle multiple services when they are running at the same host.
This is explained here:
https://github.com/Netflix/Hystrix/issues/117#issuecomment-14262713
Turbine maintains state of all these instances in order to maintain persistent connections to them and it does rely on the "hostname" and if the host name is the same then it won't instantiate a new connection to that same server (on a different port).
So the main point is, that all of your services must be registered with different hostnames. How you could do this on your local machine is described below.
UPDATE 2015-06-12/2016-01-23: Workaround for local testing
Change your hostfile:
# ...
127.0.0.1 localhost
127.0.0.1 localdomain1
127.0.0.1 localdomain2
# ...
127.0.0.1 localdomainx
And then set the hostname for your clients each to a different domain-entry like this:
application.yml:
eureka:
instance:
hostname: localdomainx

Resources