Control throughput per second - java

I have a class witch is responsible for sending data to a client and all others classes use this when they need to send data. Let's call it 'DataSender.class'.
Now the client is asking us to control the throughput to a maximum of 50 calls per second.
I need to create an algoritm on this class (if possible) to keep the number of calls in the current second and if it reaches the maximum of 50, hold the process either with a sleep or something and continue without losing data.
Maybe I have to implement a queue or something better than a simple sleep. I need sugestions or a direction to follow.
For the sake of simplicity, just imagine that everyone is using something like this and I cannot change how they call me now. post() return is syncronous but that maybe I can possibly change (not sure yet):
DataSender ds = new DataSender();
ds.setdata(mydata);
if (ds.post()) {
//data send succesfull
}

If I am not mistaken, what you are looking for is throttling or rate limiting.
As Andrew S pointed out, you will need a Queue, to hold the extra requests and a sender algorithm.
The main point is that because you are not sending the data right away, the callers need to be aware that the data is not necessarily sent when their call returns. Usually senders will not be happy, if their call returns, they assume data is sent, and then the data is lost. There are many reasons why data can be lost in this scenario. As Andrew S pointed out, making senders aware that it will be an asynchronous send queue, maybe with confirmations upon successful send, will be a safer or proper approach.
You will need to decide on the size of the queue, you have to limit the size or you can run out of memory. And you need to decide what happens with the request when queue is full. Also what happens when the end point is not accessible (server down, network issues, solar flares), keep accepting data to queue or reject / throw exception.
Hint : if you have 50 requests limit, don't blast 50 requests and then sleep for 1 second. Figure out the interval between sends, send one request, make a short interval sleep.
Pro hint : if new data sent invalidates the data that was previously requested to be sent, but not sent yet, you can optimize the data sent by removing the invalidated data from the queue. This is called Conflation. Usual example is stock market prices. Say you got price of ACME 100 ten seconds ago and for whatever reason that data was not sent. If you get a new price for ACME 101 now, it is usually not useful to send the 100 price record, just send the 101 price.

Related

Mechanism for reading all messages from a queue in one request

I need a solution for the following scenario which is similar to a queue:
I want to write messages to a queue continuously. My message is very big, containing a lot of data so I do want to make as few requests as possible.
So my queue will contain a lot of messages at some point.
My Consumer will read from the queue every 1 hour. (not whenever a new message is written) and it will read all the messages from the queue.
The problem is that I need a way to read ALL the messages from the queue using only one call (I also want the consumer to make as few requests to the queue as possible).
A close solution would be ActiveMQ but the problem is that you can only read one message at a time and I need to read them all in one request.
So my question is.. Would there be other ways of doing this more efficiently? The actual thing that I need is to persist in some way messages created continuously by some application and then consume them (also delete them) by the same application all at once, every 1 hour.
The reason I thought a queue would be fit is because as the messages are consumed they are also deleted but I need to consume them all at once.
I think there's some important things to keep in mind as you're searching for a solution:
In what way do you need to be "more efficient" (e.g. time, monetary cost, computing resources, etc.)?
It's incredibly hard to prove that there are, in fact, no other "more efficient" ways to solve a particular problem, as that would require one to test all possible solutions. What you really need to know is, given your specific use-case, what solution is good enough. This, of course, requires knowing specifically what kind of performance numbers you need and the constraints on acquiring those numbers (e.g. time, monetary cost, computing resources, etc.).
Modern message broker clients (e.g. those shipped with either ActiveMQ 5.x or ActiveMQ Artemis) don't make a network round-trip for every message they consume as that would be extremely inefficient. Rather, they fetch blocks of messages in configurable sizes (e.g. prefetchSize for ActiveMQ 5.x, and consumerWindowSize for ActiveMQ Artemis). Those messages are stored locally in a buffer of sorts and fed to the client application when the relevant API calls are made to receive a message.
Making "as few requests as possible" is rarely a way to increase performance. Modern message brokers scale well with concurrent consumers. Consuming all the messages with a single consumer drastically limits the message throughput as compared to spinning up multiple threads which each have their own consumer. Rather than limiting the number of consumer requests you should almost certainly be maximizing them until you reach a point of diminishing returns.

Design for scalable periodic queue message batching

We currently have a distributed setup where we are publishing events to SQS and we have an application which has multiple hosts that drains messages from the queue and does some transformation over it and transmits to interested parties. I have a use case where the receiving end point has scalability concerns with the message volume and hence we would like to batch these messages periodically (say every 15 mins) in the application before sending it.
The incoming message rate is around 200 messages per second and each message is no more than 10 KB. This system need not be real time, but would definitely be a good to have and also the order is not important (its okay if a batch containing older messages gets sent first).
One approach that I can think of is maintaining an embedded database within the application (each host) that batches the events and another thread that runs periodically and clears the data.
Another approach could be to create timestamped buckets in a a distributed key-value store (s3, dynamo etc.) where we write the message to the correct bucket based the messages time stamp and we periodically clear the buckets.
We can run into several issues here, since the messages would be out of order a bucket might have already been cleared (can be solved by having a default bucket though), would need to accurately decide when to clear a bucket etc.
The way I see it, at least two components would be required one which does the batching into a temporary storage and another that clears it.
Any feedback on the above approaches would help, also it looks like a common problem are they any existing solutions that I can leverage ?
Thanks

Right design in akka. - Message delivery

I have gone through some posts on how and why akka does not guarantee message delivery. The documentation, this discussion and the other discussions on group do explain it well.
I am pretty new to akka and wish to know the appropriate design for a case. For example say I have 3 different actors all on different machines. One is responsible for cookbooks, the other for history and the last for technology books.
I have a main actor on another machine. Suppose there is a query to the main-actor to search if we have some book available. The main actor sends requests to the 3 remote actors, and expects the result. So I do this:
val scatter = system.actorOf(
Props[SearchActor].withRouter(ScatterGatherFirstCompletedRouter(
routees=someRoutees, within = 10 seconds)), "router")
implicit val timeout = Timeout(10 seconds)
val futureResult = scatter ? Text("Concurrency in Practice")
// What should I do here?.
//val result = Await.result(futureResult, timeout.duration) line(a)
In short, I have sent requests to all 3 remote actors and expect the result in 10 seconds.
What should be the action?
Say I do not get the result in 10 seconds, should I send a new request to all of them again?
What if within time above is premature. But I do not know pre-hand on how much time it might take.
What if within time was sufficient but the message got dropped.
If i dont get response in within time and resend the request again. Something like this, it remain asynchronous:
futureResult onComplete{
case Success(i) => println("Result "+i)
case Failure(e) => //send again
}
But under too many queries, wont it be too many threads on the call and bulky? If I uncomment line(a), it becomes synchronous and under load might perform badly.
Say I dont get response in 10 seconds. If within time was premature, then its a heavy useless computation happening again. If messsage got dropped, then 10 seconds of valuable time wasted. In case, say I knew that the message got delivered, I would probably wait for longer duration without being skeptical.
How do people solve such issues? ACK? But then I have to store the state in actor of all queries. It must be a common thing and I am looking for right design.
I'm going to try and answer some of these questions for you. I'm not going to have concrete answers for everything, but hopefully I can guide you in the right direction.
For starters, you will need to make a change in how you are communicating the request to the 3 actors that do book searches. Using a ScatterGatherFirstCompletedRouter is probably not the correct approach here. This router will only wait for an answer from one of the routees (the first one to respond), so your set of results will be incomplete as it will not contain results from the other 2 routees. There is also a BroadcastRouter, but that will not fit your needs either as it only handles tell (!) and not ask (?). To do what you want to do, one option is to send the request to each receipient, getting Futures for the responses and then combine them into an aggregate Future using Future.sequence. A simplified example could look like this:
case class SearchBooks(title:String)
case class Book(id:Long, title:String)
class BookSearcher extends Actor{
def receive = {
case req:SearchBooks =>
val routees:List[ActorRef] = ...//Lookup routees here
implicit val timeout = Timeout(10 seconds)
implicit val ec = context.system.dispatcher
val futures = routees.map(routee => (routee ? req).mapTo[List[Book]])
val fut = Future.sequence(futures)
val caller = sender //Important to not close over sender
fut onComplete{
case Success(books) => caller ! books.flatten
case Failure(ex) => caller ! Status.Failure(ex)
}
}
}
Now that's not going to be our final code, but it's an approximation of what your sample was attempting to do. In this example, if any one of the downstream routees fails/times out, we will hit our Failure block, and the caller will also get a failure. If they all succeed, the caller will get the aggregate List of Book objects instead.
Now onto your questions. First, you ask if you should send a request to all of the actors again if you do not get an answer from one of the routees within the timeout. The answer to this question really up to you. Would you allow your user on the other end to see a partial result (i.e. the results from 2 of the 3 actors), or does it always have to be the full set of results every time? If the answer is yes, you could tweak the code that is sending to the routees to look like this:
val futures = routees.map(routee => (routee ? req).mapTo[List[Book]].recover{
case ex =>
//probably log something here
List()
})
With this code, if any of the routees timesout or fails for any reason, an empty list of 'Book` will be substituted in for the response instead of the failure. Now, if you can't live with partial results, then you could resend the entire request again, but you have to remember that there is probably someone on the other end waiting for their book results and they don't want to wait forever.
For your second question, you ask if what if your timeout is premature? The timeout value you select is going to be completely up to you, but it most likely should be based on two factors. The first factor will come from testing the call times of the searches. Find out on average how long it takes and select a value based on that with a little cushion just to be safe. The second factor is how long someone on the other end is willing to wait for their results. You could just be very conservative in your timeout, making it like 60 seconds just to be safe, but if there is indeed someone on the other end waiting for results, how long are they willing to wait? I'd rather get a failure response indicating that I should try again instead of waiting forever. So taking those two factors into account, you should select a value that will allow you to get responses a very high percentage of the time while still not making the caller on the other end wait too long.
For question 3, you ask what happens if the message gets dropped. In this case I'm guessing that the future for whoever was to receive that message will just timeout because it will not get a response because the recipient actor will never receive a message to respond to. Akka is not JMS; it doesn't have acknowledgement modes where a message can be resent a number of times if the recipient does not receive and ack the message.
Also, as you can see from my example, I agree with not blocking on the aggregate Future by using Await. I prefer using the non-blocking callbacks. Blocking in a receive function is not ideal as that Actor instance will stop processing its mailbox until that blocking operation completes. By using a non-blocking callback, you free that instance up to go back to processing its mailbox and allow the handling of the result to be just another job that is executed in the ExecutionContext, decoupled from the actor processing its mailbox.
Now if you really want to not waste communications when the network is not reliable, you could look into the Reliable Proxy available in Akka 2.2. If you don't want to go this route, you could roll it yourself by sending ping type messages to the routees periodically. If one does not respond in time, you mark it as down and do not send messages to it until you can get a reliable (in a very short amount of time) ping from it, sort of like a FSM per routee. Either of these can work if you absolutely need this behavior, but you need to remember that these solutions add complexity and should only be employed if you absolutely need this behavior. If you're developing bank software and you absolutely need guaranteed delivery semantics as bad financial implications will result otherwise, by all means go with this kind of approach. Just be judicious in deciding if you need something like this because I bet 90% of the time you don't. In your model, the only person probably affected by waiting on something that you might have already known won't be successful is the caller on the other end. By using non-blocking callbacks in the actor, it's not being halted by the fact that something might take a long time; it's already moved in to its next message. You also do need to be careful if you decide to resubmit on failure. You don't want to flood the receiving actors mailboxes. If you decide to resend, cap it at a fixed number of times.
One other possible approach if you need these guaranteed kind of semantics might be to look into Akka's Clustering Model. If you clustered the downstream routees, and one of the servers was failing, then all traffic would be routed to the node that was still up until that other node recovered.

java heartbeat implementation for a large number of clients

I've built a server application in java, where clients can connect . I've implemented a heartbeat system where the client is sending every x seconds a small message.
On the server side I save in a HashMap the time the client has sent the message , and I use a TimerTask for every client to check every x seconds if I received any message from the client.
Everything works ok for a small amount of client, but after the number of clients increase (2k+) the memory amount is very big, plus the Times has to deal with a lot of TimerTask and the program start to eat a lot of CPU.
Is there a better way to implement this? I thought about using a database and make a select the clients that didn't sent any update in a certain amount of time.
Do you think this will work better, or is a better way of doing this.
Few random suggestions:
Instead of one timer per each client, have only one global timer that examines the map of received heartbeats quite often (say 10 times per second). Iterate over that map and find dead clients. Remember about thread-safety of shared data structure!
If you want to use database, use a lightweight in-memory DB like h2. But still sounds like an overkill.
Use cache or some other expiring map and be notified every time something is evicted. This way you basically put something in the map when a client sends a heartbeat and if nothing happened with that entry within given amount of time, the map implementation will remove it, calling some sort of listener.
Use actor-based system like Akka (has Java API). You can have one actor on the server side that handles one client. It's much more efficient than one thread/timer.
Use a different data structure, e.g. a queue. Every time you receive a heartbeat, you remove client from the queue and put it back at the end. Now periodically check only the head of the queue, which should always contain the client with oldest heartbeat.

Server providing real time game status updates

Currently my game server is small (one area and ~50 AI) and each time it sends out state update packets (UDP), it sends out a complete state to each client. This creates a packet size of ~1100 bytes. Pretty much all it sends is the following information for all entities:
int uid
int avatarImage
float xPos
float yPos
int direction
int attackState
24 bytes
Edit: More efficient structure
int uid
byte avatarImage
float xPos
float yPos
byte direction & attackState
14 bytes
but I am going to need to send more information eventually for the entities. For instance I am adding to this:
float targetXPos
float targetYPos
float speed
As more data is needed to be sent for each entity, I am fast approaching and most likely already passed the maximum size of the packet. So I am trying to think of a few possible ways to fix my problem:
1) Just build up the status update packet until I run out of room and then leave out the rest. Very bad client view. Not really an option.
2) Only send the data for the N closest entities to a client. This requires that each state update I calculate the closest N for each client. This could be very time consuming.
3) Some how design the packets so that I can send multiple for the same update. Currently, the client assumes the packets are in the following structure:
int currentMessageIndex
int numberOfPCs
N * PC Entity data
int numberOfNPCs
N * NPS Entity data
The client then takes this new data and completely overwrites its copy of the state. Since the packets are complete self contained, even if the client miss a packet, it will be ok. I am not sure how I will implement the idea of multiple packets for the same update, because if I miss one of them, what then? I can't overwrite the complete, outdated state with a update, partial state.
4) Only send the actual variables that change. For instance, for each entity I add one int that is a bit mask for each field. Things such as speed, target, direction, and avatarImage won't need to be sent every update. I still come back to the issue of what happens if the client misses a packet that did actually need to update one of these values. I am not sure how critical this would be. This also requires a little more computation on both the client and server side for creating/reading the packet, but not too much.
Any better ideas out there?
I would go with number 4 and number 2.
As you have realized, it is usually better to only send updates instead of a complete game state. But make sure you always send absolute values and not deltas, so that no information is lost should a packet be dropped. You can use dead reckoning on the client side to make animations as smooth as possible under crappy networking conditions.
You have to design carefully for this so that it is not critical if a packet is lost.
As for number 2, it does not has to be time consuming if you design for it. For example, you can have your game area divided into a grid of squares where each entity is always in exactly one particular square and let the game world keep track on this. In that case, calculating the entities in the 9 surronding grids is a O(1) operation.
This type of system is commonly solved using a Dead Reckoning or predictive contract algorithm. You can't depend on all clients getting updates at the same time, so you need to predict positions based on previously known values and then validate these predictions against server-generated results.
One problem I ran into sending delta updates (basically your 4th option), is that the data can be out of order or just old, depending on how concurrent your server is, basically race conditions of multiple clients updating the server at the same time.
My solution was to send an update notification to all the clients, with a bitmask setting a bit for each item that has been updated.
Then the client requests the current value of the specific data based on the bitmask, This also allows the client to only request data it is interested in.
The advantage of this is it avoids race conditions and the client always gets the latest value.
The disadvantage is it requires a roundtrip to get the actual value.
UPDATE to demonstrate the point I am trying to make.
Presume 4 clients A,B,C,D.
A and B send simultaneous updates to a mutable state X on the server Xa and Xb. As B gets in somewhat later than A the final state of X on the server is X= Xb.
The server sends out the updated status as it gets it to all clients, so C and D get the updated status of X, as the order of delivery is indeterminant C gets Xa then Xb and D gets Xb then Xa, so at this point the clients C and D have different ideas of the state of X, one reflects what the server has the other doesn't, it has deprecated (or old) data.
On the other hand if the server just sends out a notification that X has changed to all the clients, C and D will get two status change notifications for X. They both make requests for the current state of X, and they both end up with the final state of X on the server which is Xb.
As the order of the status notification is irrelevant as there is no data in it, and the clients issue a request for the updated state on each notification they both end up with consistent data,
I hope that is more clear as to the point I was trying to make.
Yes it does increase the latency, but the designer has to decide what is more important, the latency or having all clients reflecting the same state of mutable data. This will depend on the data and the game.

Categories