Zuul and Dynamic Service Discovery (using Ribbon)

764 views
Skip to first unread message

Carey Boldenow

unread,
Dec 4, 2015, 7:31:56 AM12/4/15
to eureka_netflix
Hello,

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.

1.  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



2.  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!


Kelly A

unread,
Dec 18, 2015, 4:12:10 PM12/18/15
to eureka_...@googlegroups.com
Hi Carey -

Out of the box Zuul does not support dynamically adding a new backend service. It creates the RestClient in memory in StartServer.java, hence only happens on startup.

The team I'm on follows the practice of baking images/AMIs with the zuul build and building/deploying a new one with new changes for updates, rather than updating properties files individually on each zuul machine.  Config management across the zuul cluster can easily become inconsistent and I find it more predictable to bake the images rather than deal with config management in this case.

If you do want to update properties on the fly, instead of putting it in the actual properties file on the machine, you can hook Archaius up to a remote store - so you can update the properties in one remote location and have the change picked up by all zuul machines.  This of course makes the images now not so immutable in a sense - so it's a tradeoff.
To mitigate the need for a restart, you can do something like add a pre routing groovy script that checks to see if a particular RestClient exists in memory and if not, creates it on the fly.
Again, some would argue that it's better to rebuild Zuul each time you add a service so that you can control exactly what your configuration looks like through code.

On a side note, I would not use Zuul for service-to-service communication. You are better off having each service communicate with each other via Ribbon/Eureka.  Otherwise, Zuul becomes a single point of failure for all service communication and a bottleneck as well.  Not to mention you'll either need a load balancer in front of your zuul cluster, or have static IPs for zuul that all services know about (limits scalability) or each service will use Ribbon/Eureka to locate zuul - which is rather redundant.  

If you do direct service to service communication, you could probably reduce the amount of services that zuul has to know about, which could also reduce the amount of updates you'll need to do to zuul.

In my team, we use Zuul for the edge only, for servicing requests coming from end users to backend services.



--
You received this message because you are subscribed to the Google Groups "eureka_netflix" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eureka_netfli...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages