Elasticsearch REST High Level Client - spring

In one of my projects, my microservice XYZ talks to ABC. ABC has a elasticsearch REST high level client that queries a particular ES index. Let's call the endpoint defined in XYZ where XYZ talks to ABC as "/getData"
I have noticed that when /getData is not called often, the first invocation of it times out. For example, if the endpoint has not been called in 24 hours and then it gets called, it will timeout but subsequent calls don't timeout. And the pattern I have observed is that subsequent calls are also faster in returning the response.
I am using Spring, so is this some kind of lazy loading happening? Where the connections to ES become idle if they haven't been used in a while and if so, can I configure it somehow to avoid this problem.

Related

GRPC: Spring boot: How to warm up a grpc client. Especially to make it resolve domain names

The issue is: A grpc client is taking too much time on its first call. And after debugging, it was the domain name resolution that is taking that amount of time.
Is there any way to warm up the grpc clients just after the application starts?
Update: The request eventually succeeds, but the first call takes so much time, the consecutive calls are much faster.
And Im using this library https://github.com/yidongnan/grpc-spring-boot-starter
When created, the ManagedChannel has not performed any I/O. It will lazily initialize itself on the first RPC or if you call managedChannel.getState(true).

Elasticsearch high level REST client - Indexing has latency

we have started using the high level REST client finally, to ease the development of queries from backend engineering perspective. For indexing, we are using the client.update(request, RequestOptions.DEFAULT) so that new documents will be created and existing ones modified.
The issue that we are seeing is, the indexing is delayed, almost by 5 minutes. I see that they use async http calls internally. But that should not take so long, I looked for some timing options inside the library, didn't find anything. Am I missing anything or the official documentation is missing for this?
Since refresh_interval: 1 in your index settings, it means it is never refreshed unless you do it manually, which is why you don't see the data just after it's been updated.
You have three options here:
A. You can call the _update endpoint with the refresh=true (or refresh=wait_for) parameter to make sure that the index is refreshed just after your update.
B. You can simply set refresh_interval: 1s (or any other duration that makes sense for you) in your index settings, to make sure the index is automatically refreshed on a regular basis.
C. You can explicitly call index/_refresh on your index to refresh it whenever you think is appropriate.
Option B is the one that usually makes sense in most use cases.
Several reference on using the refresh wait_for but I had a hard time finding what exactly needed to be done in the rest high level client.
For all of you that are searching this answer:
IndexRequest request = new IndexRequest(index, DOC_TYPE, id);
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);

Invoking 1 AWS Lambda with API Gateway sequentially

I know there's a question with the same title but my question is a little different: I got a Lambda API - saveInputAPI() to save the value into a specified field. Users can invoke this API with different parameter, for example:
saveInput({"adressType",1}); //adressType is a DB field.
or
saveInput({"name","test"}) //name is a DB field.
And of course, this hosts on AWS so I'm also using API Gateway as well. But the problem is sometimes, an error like this happened:
As you can see. API No. 19 was invoked first but ended up finishing later
(10:10:16:828) -> (10:10:18:060)
While API No.18 was invoked later but finished sooner...
(10:10:17:611) -> (10:10:17:861)
This leads to a lot of problems in my project. And sometimes, the delay between 2 API was up to 10 seconds. The front project acts independently so users don't know what happens behind. They think they have set addressType to 1 but in reality, the addressType is still 2. Since this project is large and I cannot change this kind of [using only 1 API to update DB value] design. Is there any way for me to fix this problem ?? Really appreciate any idea. Thanks
If updates to Database can't be skipped if last updated timestamp is more recent than the source event timestamp, we need to decouple Api Gateway and Lambda.
Api Gateway writes to SQS FIFO Queue.
Lambda to consume SQS and process the request.
This will ensure older event is processed first.
Amazon Lambda is asynchronous by design. That means that trying to make it synchronous and predictable is kind of waste.
If your concern is avoiding "old" data (in a sense of scheduling) overwrite "fresh" data, then you might consider timestamping each data and then applying constraints like "if you want to overwrite target data, then your source timestamp have to be in the future compared to timestamp of the targeted data"

How to limit rate of out going http calls in scaled microservice?

I have a scenario in which my microservice is scaled to 3 instances. Each service makes http calls to third party service. However, the third party service has a rate limit i.e. it cannot accept more than 1000 requests per second. Now that I have 3 instances of same service running its hard to keep track of count. Any solutions that could help me implement this?
You can use Circuit Breaker pattern and tools like Hystrix in such a scenario.
My answer is based on assumption that each service is independent and don't interact with each others and can possibly scaled up or down.
Use Redis data cache service, introduce a variable there. Each service will be able to refer that variable and will update when ever they make a API call, write some conditions so no service is allow to make calls if its reach to 1000 for that specific second .
Hence they will not be able to make more than 1000 call per seconds.

Spring Cache For Pending Method Calls

Let's say I'm writing a Spring web-service that gets called by an external application. That application requests data that I need to load from an external resource. Furthermore, the design has it that it calls my service more than once with different parameters. In other words, the user sitting in front of the application presses one button, which generates a bunch of requests to my web-service in a very short time frame.
My web-service parses the parameters and comes up with necessary requests to the external resource. The logic has it that it may cause calling the external resource with the same parameters over and over again, which makes this the ideal candidate for caching.
Example:
The user presses that one button in the application
Application initiates ten requests to my web-service
My web-service receives them in parallel
After analysing the parameters of all requests, overall I'd need to call the external resources 15 times, but the parameters are mostly equal and only show that three calls would be enough to serve the 15 intended calls.
However, one call to the external resource may take some time.
As far as I understand how Spring does caching it writes the result of a #Cachable method into the cache. Apparently this means that before it treats another invocation of that method with the same parameters as cache hit, it must have a result of a previous invocation. This means that it doesn't provide support for pending method calls.
I need something like "Hey, I just saw a method invocation with the same parameters a second ago, but I'm still waiting for the result of that invocation. While I can't provide a result yet, I will hold that new invocation and reuse the result for it."
What are my options? Can I make Spring do that?
You can't make Spring do that out-of-the-box for very good reasons. The bottom line is that locking and synchronizing is very hard using a specific cache implementation so trying to do that in an abstraction is a bit insane. You can find some rationale and some discussion here
There is a discussion of using ehcache's BlockingCache SPR-11540
Guava also has such feature but the cache needs to be accessed in a very specific way (using a callback) that the CacheInterceptor does not really fit. It's still our plan to try to make that work at some point.
Do not forget that caching must be transparent (i.e. putting it on and off only leads to a performance change). Trying to parse arguments and compute what call should be made to your web service has high chances to lead to side effects. Maybe you should cache things at a different place?

Resources