Dynamically Configuring a Zuul Proxy during Runtime? - spring-cloud

I have a url path that looks like this:
/{identifier}/rest/of/resource/path
If the identifier is A then the request should go to service_I. If the identifier is B then the request should also go to service_I. If the identifier is C, then the request should go to service_II, and so on.
Later on a new identifiers M and N is added to the system and their requests should be routed to service_IV.
Is it possible to dynamically configure a Spring cloud zuul proxy to perform the tasks described above?
Edit
This question offered contains a different way to examine the question.
In it Zuul has the following configuration:
zuul:
routes:
<service_id>:
path: /path/**
Zuul will collaborate with Eureka to find the service-id and return the host parameters so that the service can be accessed. What if instead of /path we have /{userID} and the userID instances are distributed across several service_id hosts?
Can Zuul / the DiscoveryClient query Eureka for both the service_id and the userID to figure out which host is hosting the particular userID?

You would need to write a custom ZuulFilter to accomplish this. Take a look at the PreDecorationFilter for some hints as this is the filter responsible for handling /path where the path is a service-id (among other things).

Related

Querying Remote State Stores in Kubernetes (Interactive Queries)

Are there any recommendations on querying remote state stores between application instances that are deployed in Kubernetes? Our application instances are deployed with 2 or more replicas.
Based on documentation
https://kafka.apache.org/10/documentation/streams/developer-guide/interactive-queries.html#id7
streams.allMetadataForStore("word-count")
.stream()
.map(streamsMetadata -> {
// Construct the (fictituous) full endpoint URL to query the current remote application instance
String url = "http://" + streamsMetadata.host() + ":" + streamsMetadata.port() + "/word-count/alice";
// Read and return the count for 'alice', if any.
return http.getLong(url);
})
.filter(s -> s != null)
.findFirst();
will streamsMetadata.host() result in the POD IP? And if it does, will the call from this pod to another be allowed? Is this the correct approach?
streamsMetadata.host()
This method returns whatever you configured via application.server configuration parameter. I.e., each application instance (in your case each POD), must set this config to provide the information how it is reachable (e.g., its IP and port). Kafka Streams distributes this information for you to all application instances.
You also need to configure your PODs accordingly to allow sending/receiving query request via the specified port. This part is additional code you need to write yourself, i.e., some kind of "query routing layer". Kafka Streams has only built-in support to query local state and to distribute the metadata about which state is hosted where; but there is no built-in remove query support.
An example implementation (WordCountInteractiveQueries) of a query routing layer can be found on Github: https://github.com/confluentinc/kafka-streams-examples
I would also recommend to checkout the docs and blog post:
https://docs.confluent.io/current/streams/developer-guide/interactive-queries.html
https://www.confluent.io/blog/unifying-stream-processing-and-interactive-queries-in-apache-kafka/

How do I seed default data to Mongo db (or any database) in a microservice architecture?

I have a use case where there are multiple microservices and one of them deals with roles and resources(let's call this microservice as A). Resources are just endpoints.
A maintains a collection(let's call this X) to store all the resources from different microservices. For each microservice other than A, I would like to store all of its resources(endpoints) into X the first time this microservice boots up.
I am thinking of having a json file with all the resources in each microservice and calling A's endpoint to add resources whenever a microservice boots up.
Is there any idiomatic way to do this?
Consider the use of Viper so you can set default data from multiple different sources like yaml, json, remote config like etcd, live watch of files among others. You can algo configure the call to and endpoint with it's remote configuration feature.

Sticky Requests for K8 hostname based on primary key (modulo routing)

Is it possible to configure k8 so that based on some data in a request it is always routed to the same hostname?
Perhaps something using stateful sets? Can we do a modulo based routing so that a request like
POST /myroute
{
_id : 1
}
will always go to one hostname,
and a request like
POST /myroute
{
_id : 2
}
will always go to another??
Or is there away so that each host can ignore requests based on the payload. This is a pretty standard routing method, similar to a distributed hash table.
Sorry if I'm not explaining this well. But does anyone have any example of this type of k8 configuration?
You can use vulcand as Ingress controller.It has very good routing-language
Also nginx plus as Ingress can be a solution

Embedding custom metadata with Service Fabric application/service

The objective that I have is to run multiple applications with some metadata embedded into applications/services so that I could query applications/services using the metadata. Is this possible?
I was looking at the following post and the answer hints at this possibility, but no specific details on how to achieve the result.
The primary piece of "metadata" you get is the service/application instance name. That's what I talked about in my other post. The way that works is by creating each service/application instance with a name that contains some information clients can use when resolving them. Clients can then query Service Fabric for named application/service instances and connect to a specific one. A service/application instance name is URI, so you can use a path hierarchy to categorize information.
Continuing with the audio/video example: Let's extend that example so we have an application that can perform specific tasks for specific media formats for audio or video. Each combination of task + media format is a unique named service instance, resulting in a deployment that looks something like this:
Application:
fabric:/avapp
Services:
fabric:/avapp/video/encoding/mp4
fabric:/avapp/video/encoding/h264
fabric:/avapp/video/captioning/english
fabric:/avapp/video/captioning/czech
fabric:/avapp/audio/encoding/aac
fabric:/avapp/audio/encoding/mp3
etc.
Now clients can query Service Fabric to discover what services are available:
FabricClient fabricClient = new FabricClient();
System.Fabric.Query.ServiceList services = await fabricClient.QueryManager.GetServiceListAsync(new Uri("fabric:/avapp"));
Then you can simply query the list of services with LINQ. For example, if I want to see all services that do video encoding:
services.Where(x => x.ServiceName.AbsolutePath.Contains("video/encoding"));
And then you can resolve an address for a specific service to connect to it:
ServicePartitionResolver resolver = ServicePartitionResolver.GetDefault();
ResolvedServicePartition servicePartition = await resolver.ResolveAsync(new Uri("fabric:/avapp/video/encoding/h264"), new ServicePartitionKey(1), cancellationToken);
ResolvedServiceEndpoint endpoint = servicePartition.GetEndpoint();
There's a bit more to the address resolution part (see here), but that's the general idea.
Application instances also allow you to set custom application parameters (key-value pairs) that can be set per instance at creation time. They don't show up in the application name, but you get that information back when you ask Service Fabric for a list of running application instances. That can potentially also be used as metadata by clients when they need to decide what application to connect to.
Update: More info on application instance parameters:
When you create a new application instance you can supply a set of key-value pairs in the application description. Then when you query Service Fabric for application instances you get back a list of Application result objects that have said parameters. This also shows up in Visual Studio, in your application project, where you have environment-specific application parameter files. Visual Studio extracts those key-value pairs from the XML files and uses them in the application description when it creates an instance of your application.

Spring cloud - Zuul - aggregate responses

How could Zuul be used to aggregate results of two endpoints? i.e.
Suppose /api/notes request being made.
Zuul is suuposed to invoke /notes/from/source/1 and/notes/from/source/2 endpoints
Aggregate results receied fom both the endpoints
Send aggregated results to client who initiated the results
Can this be done easily with Zuul? If not, I don't see any other facility that Zuul provides other than providing a filter chain.
It can't be done automatically. You need to write a zuul filter to do this.