Spring Cloud Load Balancer - Is there a way to see which instance is choosen? - spring-cloud

We're switching from Ribbon to Spring Cloud Load Balancer, and thus far things seem to work. However I want to be able to see which instance is chosen on each request to verify the behavior.
Is there a debug flag or some other way to see which instance SCLB is choosing on each request?

The selected service instances are logged for debug in various places on the client side, for example in ReactorLoadBalancerExchangeFilterFunction, in RetryLoadBalancerInterceptor, in RetryableLoadBalancerExchangeFilterFunction, etc. Also,for WebClient-backed load-balancing you can enable setting instance Id as a cookie. You can also enable Micrometer support, which will register various useful metrics, including instance ids. Additionally, you can implement your own logging mechanism using the LoadBalancerLifecycle callbacks.

Related

Manage Fault Tolerance with Feign, Ribbon and Eureka

I want to implement a resilient microservices architecture using Feign Client,Ribbon and Eureka so I encountered an issue. When a microservices target is down I want to redirect to another instance of microservices without the user seeing it. For example, I have 4 instances of microservices B and one instance A :
The Browser client call A then A call B1 but B1 is down => A redirect automatically to B2, B2 is KO then A call B3 and B3 is up then it returns a response to A. A returns response to the browser client.
How I could implement it, please.
Thanks in advance.
Basically, Ribbon should already find instances that are alive for you - firstly, Eureka stores and updates information on which instances are alive and, secondly, Ribbon runs health-check requests to the instances. If that is not working correctly for you, you can try customising the polling intervals for Ribbon. If you want a failed request to be repeated against a different instance, you can use Spring Cloud Netflix Ribbon with Spring Retry (see documentation).
Having said that, since Spring Cloud Ribbon is now in maintenance mode and will not be making it into the 2020.0.0 release train, I would definitely not encourage adding it at this point. The available alternative is Spring Cloud LoadBalancer. It supports retrieving the instances that are alive from Service Discovery (either with or without caching and health-checks. It does not support retries at this point, but there's an issue for it in the project backlog.

Controlling the user experience when doing canary or A/B deployments with Istio

I have an application with multiple services called from a primary application service. I understand the basics of doing canary and A/B deployments, however all the examples I see show a round robin where each request switches between versions.
What I'd prefer is that once a given user/session is associated with a certain version it stays that way to avoid giving a confusing experience to the user.
How can this be achieved with Kubernetes or Istio/Envoy?
You can do this with Istio using Request Routing - Route based on user identity but I don't know how mature the feature is. It may also be possible to route based on cookies or header values.
We've been grappling with this because we want to deploy test microservices into production and expose them only if the first request contains a "dark release" header.
As mentioned by Jonas, cookies and header values can in theory be used to achieve what you're looking for. It's very easy to achieve if the service that you are canarying is on the edge, and your user is directly accessing.
The problem is, you mention you have multiple services. If you have a chain where the user accesses edge service A which is then making calls to service B, service C etc, the headers or cookies will not be propagated from one service to another.
This is the same problem that we hit when trying to do distributed tracing. The Istio documents currently have this FAQ:
https://istio.io/faq/distributed-tracing/#istio-copy-headers
The long and short of that is that you will have to do header propagation manually. Luckily most of my microservices are built on Spring Boot and I can achieve header propagation with a simple 5-line class that intercepts all outgoing calls. But it is nonetheless invasive and has to be done everywhere. The antithesis of a service mesh.
It's possible there is a clever way around this but it's hard to infer from the docs what is possible and what isn't. I've seen a few github issues raised by Istio developers to address this but every one I've seen has gone stale after initial enthusiasm.

Spring Cloud: How to manage requests on Zuul to another services?

Actually I would like to understand correct approach for managing requests among several microservices, one of them is Zuul:
I have Zuul-app, which is proxy before my microservice. Zuul started on port 7777 and declares API like /api/service1/get or /api/service2/get. On every service I have echo-endpoint which is available localhost:7777/api/service1/get and work well.
But those echo-endpoints are available directly from corresponding services. Thus I can make request from Postman, let's say, to service1/get/ and service2/get
As far as I understand anybody can call those services through Zuul or directly from those services. So what is difference and what is real value of Zuul for such case (instead of Zuul can authorize users, let's say as proxy microservice)
So what is correct approach for using Zuul for microservices ?
Your question looks like you are asking two things. What is the purpose and how to use it. Going to answer the first one.
Its purpose is to be the service in front of all the other services you have. Like front door to your system.
Rest of the services should be hidden of outside world, behind proxy service.
The purpose is to route all the services from one place, so with netflix-zuul you are able to intercept the request, manipulate, authenticate, route...
You can integrate service discovery (netflix-eureka) so your services will be registered there, and you don't need to deal with urls of your services, you can access them by path you defined and registered service ids.
You can integrate load balancing (netflix-ribbon) across your system.
You can control the interactions between your services by adding latency tolerance and fault tolerance logic (netflix-hystrix). So you can provide fallback options when error occurs..
And so on...

Health check API for message-driven beans

I'd like to be able to do a health check on a deployed Message-Driven Bean in Production. My initial idea was to add a health() method ensuring that the JMS Queue (for reading) and the Database (for writing) are both available, and then expose this health method as a REST API. Unfortunately as a MDB isn't injectable like the other types of EJBs I cannot get a reference to it from my REST controller...
Is there a way to expose a message-driven bean's methods through a REST API ? Or any other way to achieve my initial goal ?
EDIT
A little precision : I don't want to just check that the resources are available, but also that the EJB can communicate with them (by pinging them from inside the EJB instance). This would not only validate that the resources are available (which could indeed be done some other way), but more importantly for me also that the resources bindings are valid and that the resources injection is working.
I think it's not possible the way you want to have it. The reason is, that unlike other EJBs, a MDB solely acts upon arrival of a message and not by any other call to it.
But you may do it the other way round and inject some class into the MDB which you call on any message you receive. That way you'd have a constant "I'm alive" ping, provided that you get messages continuously.
Other than that your only chance is to use the mechanisms of your container which usually can provide some information about its deployed and running components which you may query.

Service Fabric dynamic partitioning

So I am doing some research into using Service Fabric for a very large application. One thing I need to have is a service that is partitioned by name, which seems fairly trivial at the application manifest level.
However, I really would like to be able to add and remove named partitions on the fly without having to republish the application.
Each partition represents our equivalent of a tenant, and we want to have a backend management app to add new tenants.
Each partition will be a long-running application that fires up a TCP server that uses a custom protocol, and I'll need to be able to query for the address by name from the cluster.
Is this possible with Service Fabric, and if so is there any documentation on this, or something I should be looking for?
Each partition represents our equivalent of a tenant, and we want to have a backend management app to add new tenants.
You need to rethink your model. Partitioning is for distributing data so it accessible fast, for read and write. But within the same logical container.
If you want to do some multitenant in Service Fabric you can deploy an Application multiple times to the cluster.
From Visual Studio it seems you can only have one instance of an Application. This is because in the ApplicationManifest.xml there are DefaultServices defined. This is okay for developing on the local Service Fabric cluster. For production you might want to consider deploying the application with powershell, this will open up the possibility to deploy the same application multiple times with settings for each instance(like: tenant name, security, ... )
And not only Applications can be deployed multiple times, stateful/stateless services as well. So you could have one application and for each tenant you deploy a service of a certain type. Services are findable via the naming service inside Service Fabric, see the FabricClient class for more info on that.
It is not possible to change the partition count for an existing application.
From https://azure.microsoft.com/en-us/documentation/articles/service-fabric-concepts-partitioning/#plan-for-partitioning (emphasis mine):
In rare cases, you may end up needing more partitions than you have initially chosen. As you cannot change the partition count after the fact, you would need to apply some advanced partition approaches, such as creating a new service instance of the same service type. You would also need to implement some client-side logic that routes the requests to the correct service instance, based on client-side knowledge that your client code must maintain.
You are encouraged to do up-front capacity planning to determine the maximum number of partitions you will need - and if you end up needing more, you'll need to implement some special client side handling to cope.
We had the same problem and ended up creating an instance of the service for each tenant. This is pretty easy to do and will scale to any number of tenants.