Controlling number of http request coming to system - Backpressure - rest

We had a use case where our client by mistake sends 10000 request, for each request we had to immediately send a ID and then enrich the data with multiple DB calls/rest call and finally response back to Kafka topic. Due to this much processing the whole system went down including the underlined system as along with Kakfa we also publish to MQ which again goes for further processing.
Ask is to control the number of requests client can send, we though of controlling it to store the threshold in DB based on per day or per hours and start rejecting once they reach the threshold but this requires computation and DB hits.
Is there any tool or out of box solution with minimum effort and without adding performance load to system? We are looking for some kind of Back pressure technique like in Spring webflux etc.
It is spring boot application on Java 11.

Backpressure works the other way around, when you are consuming a client that is emitting more than you can process. What you are looking for is Rate Limiter.
You can take a look at the Resilience4J Rate Limiter

Related

Message bus best practices to send updates

I would like to understand what are the best practices when using a message bus to update several services.
The basic show case is to send the full object through the bus and everyone listening can immediately get the data and process it.
Other option is to send the minimal necessary data through the bus, 3/4 fields, and then each listening service should request the main application to fetch the required data to process it.
The main application is not waiting for anyone to complete their work, and we are talking about an object with 30 to 40 fields and no more than 10kb, most usually less than 5kb.
Is there any architectural advantage using the second approach?
Design is always about tradeoff between options.
Option-1: This is preferred and simple to implement and truly decouple from producer. If require compression can be enable to reduce the size, though compression can slightly reduce the overall throughput.
This approach will require more disk space and application memory.
Ex: Json payload.
Your example appears to be more suitable with option-1.
Option-2: This can be use if purpose of kafka message is to notify with minimal information and additional details could be file or independent object/multimedia urls.
One Reference implementation is in AWS S3 event streaming, where S3 publish the message arrival information(ex:someone uploaded file) and S3 url, then consumer can use this information to process. This approach require object storage or multimedia host to allow the consumer to connect and download/process particular event.

Forwarding messages coming from Kafka Topic

I am in the process of designing a system which acts like a message forwarder from one system to another system. I have several options to go for but I would like to apply the best option which provides less resource consumption (cpu, ram) and latency. Thus, I need your recommendation and view on this.
We assume that messages will be streaming to our system from a topic in Kafka. We need to forward all the messages from the topic to another host. There can be different strategies for this purpose.
Collect certain number of messages let's say 100 messages (batch processing) and send them at once within a single HTTP message.
When one message is received, system will send this message as the http POST request to the target host.
Open webSocket between our system and the target host and send messages.
Behave like a Kafka producer and send messages to topic.
Each of them might have advantages and disadvantages. I have concern that system may not handle the high amount of messages coming. Do you have any option other than these 4 items? Which is the best option you think in terms of what?
How important your latency requirement is ?
HTTP is quite slow, compared to an UDP based messaging system, but maybe you don't need a so tailored latency.
Batching your messages will increase latency, as you may know.
But it's disturbing because the title of this page is "rest - forwarding" =).
Does it has to be REST ( so HTTP) ? because it seems you can as well envisage to act like a kafka producer, if so, it's not REST.
The memory footprint of Kafka may be a bit high (Java lib), but no so much.
Do you work on embedded system (willing to reduce memory footprint ?)
For CPU purposes.. it depends with what we're comparing Kafka, but I still think Kafka is quite optimised when asking for performance.
Think we lack more information about this "another host" , could you give more details about its purpose ?
Yannick
I think you are looking for Kafka Streaming in this scenario. Although from an efficiency point of view maybe some hadoop stack implementation (Flume) or Spark would be less consuming, not sure, depends on amount of data, network jumps, disk used, amount of memory.
If you have huge amounts of messages those distributed solutions should be your right approach not a custom REST client.

Will WebFlux have any bottlenecks in such architecture?

We're currently about to migrate from monolithic design to the microservice architecture, trying to choose the best way to replace JAX-WS with RESTful and considering to use Spring WebFlux.
We currently have an JAX-WS endpoint deployed at Tomcat EE serving requests from third-party clients. Webservice endpoint makes a long running blocking call to the database and then sends a SOAP-response to the client with a data retrieved from DB (Oracle).
Oracle DB will be replaced with one of NoSQL databases soon (possibly it will be MongoDB). Since MongoDB supports asynchronous calls we're considering to substitute current implementation with a microservice exposing REST endpoint based on WebFlux.
We have about 2500 req/sec at peaks, so current endpoint often gets down with a OutOfMemoryError. It was a root cause that pushed us towards migration.
My thoughts are to create a non-blocking endpoint which will call MongoDB in asynchronous manner and send a REST-response to the client. So I have a few questions considering basic features that WebFlux provides:
As far as I concerned there is a built-in backpressure control at
the business-level (not TCP flow control) in WebFlux and it works
generally via Reactive Streams. Since our clients are not
reactive, does it means that such way of a backpressure control is
not implementable here?
Suppose that calls to a new database remains long-running in a new
architecture. Since Netty uses EventLoop to serve incoming
requests, is there possible a situation when the microservice has
accepted all incoming HTTP connections, invoke an async call to the
db and subscribed a resulted Mono to the scheduler, but, since
the request quantity keeps growing explosively, application keep
creating new workers at scheduler pools that leads to a
crashing? Is this a realistic scenario?
Suppose that calls to the database remained synchronous. Is there a
way to handle them using WebFlux in a such way that microservice
will remain reachable under load?
Which bottlenecks can be found in such design? Does this solution
looks adequate?
Does Netty (or Reactor-Netty, or whatever) has a tool to limit a
quantity of requests processing simultaneously? Say I would to limit
the endpoint to serve not more than 100 parallel requests and skip
all requests above that point, is it possible?
Suppose I will create a huge amount of threads serving async (or
maybe sync) calls to the DB. Where is a breaking point when the
application will crash or stop responding to the incoming
HTTP-requests? What will happened there - we will ran out of memory
or..?
Finally, there were no any major issues concerning perfomance during our pilot project. But unfortunately we didn't take in account some specific Linux (and also OpenShift) TCP tuning props.
They may significanly affect the overall perfomance, in our case we've gained about 10 times more requests after tuning.
So pay attention to the net.core.somaxconn and other related parameters.
I've summarized our expertise in the article.

Lagom: Read Side Processor vs Broker Api to build read model

Reading lagom documentation, we can build read side with both read side processor and message broker api.
What are advantages to use one over another?
(Let's take into account general ReadSide support (not Cassandra and Jdbc which implement event offset tracking).
Prototyping some application, I've noticed that Read Side Processor has higher latency between events persistence into event log and read model update than Broker Api.
Prototyping some application, I've noticed that Read Side Processor
has higher latency between events persistence into event log and read
model update than Broker Api.
This is the eventual consistency delay. You can change this with a setting in your application.conf:
cassandra-query-journal.eventual-consistency-delay = 1s
You have to decide what is necessary for your application. You can set this to zero, but it is rarely necessary.

Is a message queue like RabbitMQ the ideal solution for this application?

I have been working on a project that is basically an e-commerce. It's a multi tenant application in which every client has its own domain and the website adjusts itself based on the clients' configuration.
If the client already has a software that manages his inventory like an ERP, I would need a medium on which, when the e-commerce generates an order, external applications like the ERP can be notified that this has happened to take actions in response. It would be like raising events over different applications.
I thought about storing these events in a database and having the client make requests in a short interval to fetch the data, but something about polling and using a REST Api for this seems hackish.
Then I thought about using Websockets, but if the client is offline for some reason when the event is generated, the delivery cannot be assured.
Then I encountered Message Queues, RabbitMQ to be specific. With a message queue, modeling the problem in a simplistic manner, the e-commerce would produce events on one end and push them to a queue that a clients worker would be processing as events arrive.
I don't know what is the best approach, to be honest, and would love some of you experienced developers give me a hand with this.
I do agree with Steve, using a message queue in your situation is ideal. Message queueing allows web servers to respond to requests quickly, instead of being forced to perform resource-heavy procedures on the spot. You can put your events to the queue and let the consumer/worker handle the request when the consumer has time to handle the request.
I recommend CloudAMQP for RabbitMQ, it's easy to try out and you can get started quickly. CloudAMQP is a hosted RabbitMQ service in the cloud. I also recommend this RabbitMQ guide: https://www.cloudamqp.com/blog/2015-05-18-part1-rabbitmq-for-beginners-what-is-rabbitmq.html
Your idea of using a message queue is a good one, better than database or websockets for the reasons you describe. With the message queue (RabbitMQ, or another server/broker based system such as Apache Qpid) approach you should consider putting a broker in a "DMZ" sort of network location so that your internal ecommerce system can push events out to it, and your external clients can reach into without risking direct access to your core business systems. You could also run a separate broker per client.