Since I don't have the code here I'll try to be as clear as I can...
I'm developing a rest service in java that will get some params (number of threads, ammount of messages) and will create the threads (via loop) and send this number of messages via MQ (I'm passing the number of mssages when creating the thread).
So for an example if someone sends 50 threads and 5000 msgs it will send 2.5M msgs...
Now my question is how could I create another rest service to monitor all those threads and give me a % of conclusions on the messages sent.
I'm considering calling this service to update a progress bar every 2 secs via ajax.
A simplified approach is to create a class to keep track of the statistics the status bar will need to display. For example:
public class MessageCreatorProgress {
private final int totalMessagesToBeCreated;
private final AtomicInteger successCount;
private final AtomicInteger failureCount;
// constructor to initialize values
// increment methods
// get methods
}
In the initial request which starts the threads, construct the threads with a shared instance of an MessageCreatorProgress. For example:
// endpoint method to create a bunch of messages
public String startCreatingMessages(CreateMessagesRequest request) {
MessageCreatorProgress progress = new MessageCreatorProgress(requesst.getThreadCount * request.getMessageCountPerThread());
for (...) {
new MyMessageCreator(progress, request.getSomeParameter(), ....).start();
}
String messageProgressId = some unique value...
// Store MessageCreatorProgress in the session or some other shared memory,
// so it can be accessed by subsequent calls.
session.setAttribute(messageProgressId, progress);
return messageProgressId;
}
Each MyMessageCreator instance would for example call progress.incrementSuccess() as a last step, or progress.incrementFailure() for an exception.
The AJAX call passes the messageProgressId to the status endpoint which knows how to access the MessageCreatorProgress:
// endpoint method to get the message creation progress
// transform to JSON or whatever
public MessageCreatorProgress getMessageCreationProgress(String messageProgressId) {
return session.getAttribute(messageProgressId);
}
A more complex approach is to use a database - for example when the AJAX call will not hit the same server running the threads which are creating the messages. When a thread is successful or has an exception it can update a record associated with messageProgressId, and the AJAX endpoint checks the database and constructs a MessageCreatorProgress to return to the client.
Related
Lets say you have a process that needs to continuously check the time of a "Service". I want to to design this process to eliminate and log a "Service" that is about to timeout from a thread safe list.
What would be a good way to keep checking a CopyOnWriteArrayList of type "Services" for timeouts?
Keep in mind other "systems" may need to add a service to the list at any time. So we must keep checking for the duration of what ever process is adding another service to the list.
Consumer(){
//some method that adds service objects to the list."
}
public class Service(){
// time would represent the time it was created by some system.
int time;
// unique id of service.
String id;
}
public class ServiceTimeoutProcesser{
private CopyOnWriteArrayList inputCopyOnWriteArrayList;
private TimetoLive timetoLive;
ExampleProcess(CopyOnWriteArrayList<Service> inputCopyOnWriteArrayList, TimetoLive timetoLive){
this.inputCopyOnWriteArrayList = inputCopyOnWriteArrayList;
this.timetolive = timetolive;
}
//Ultimately I would call this over and over till triggered to stop ....
private void KeepCheckingTime(inputCopyOnWriteArrayList){
for(Service service : inputCopyOnWriteArrayList){
Long currentTime = System.currenttime();
if(service.time - currentTime > timeTolive){
//remove service from list
// logged that you kicked out service
// maybe add service to some other list to be re processed?
}
}
}
Example of an inefficient idea would be to do something like..
// create some kind of infinite loop
while(true){
//call KeepCheckingTime(inputCopyOnWriteArrayList)
}
// If you think this is a good solution tell me why.
Ideally I would want a thread to call this multiple times ,but a single thread would die after it executes right? resulting in me being unable to log a failed "Service " if it was considered expired after that single thread finished execution. I know thread pools could be created but, I don't always know how many threads I need to kick off in compared to the size of the list. For example I create 5 threads in a thread pool .....they execute KeepCheckingTime. What if all my threads finish before any "Service" expire, or fail the case mentioned above.
I've a program with the following mapPartition function:
public void mapPartition(Iterable<Tuple> values, Collector<Tuple2<Integer, String>> out)
I collect batches of 100 from the inputted values & send them to a web-service for conversion. The result I add back to the out collection.
In order to speed up the process, I made the web-service calls async through the use of Executors. This created issues, either I get the taskManager released exception, or AskTimeoutException. I increased memory & timeouts, but it didn't help. There's quite a lot of input data. I believe this resulted in a lot of jobs being queued up with ExecutorService & hence taking up lots of memory.
What would be the best approach for this?
I was also looking at the taskManager vs taskSlot configuration, but got a little confused on the differences between the two (I guess they're similar to process vs threads?). Wasn't sure at what point do I increase the taskManagers vs taskSlots? e.g. if I've got three machines with 4cpus per machine, so then should my taskManager=3 while my taskSlot=4?
I was also considering increasing the mapPartition's parallelism alone to say 10 to get more threads hitting the web-service. Comments or suggestions?
You should check out Flink Asyncio which would enable you to query your webservice in an asynchronous way in your streaming application.
One thing to note is that the Asyncio function is not called multithreaded and is called once per record per partition sequentially, so your web application needs to deterministically return and potentially return fast for the job to not being held up.
Also, potentially higher number of partitions would help your case but again your webservice needs to fulfil those requests fast enough
Sample code block from Flinks Website:
// This example implements the asynchronous request and callback with Futures that have the
// interface of Java 8's futures (which is the same one followed by Flink's Future)
/**
* An implementation of the 'AsyncFunction' that sends requests and sets the callback.
*/
class AsyncDatabaseRequest extends RichAsyncFunction<String, Tuple2<String, String>> {
/** The database specific client that can issue concurrent requests with callbacks */
private transient DatabaseClient client;
#Override
public void open(Configuration parameters) throws Exception {
client = new DatabaseClient(host, post, credentials);
}
#Override
public void close() throws Exception {
client.close();
}
#Override
public void asyncInvoke(final String str, final AsyncCollector<Tuple2<String, String>> asyncCollector) throws Exception {
// issue the asynchronous request, receive a future for result
Future<String> resultFuture = client.query(str);
// set the callback to be executed once the request by the client is complete
// the callback simply forwards the result to the collector
resultFuture.thenAccept( (String result) -> {
asyncCollector.collect(Collections.singleton(new Tuple2<>(str, result)));
});
}
}
// create the original stream (In your case the stream you are mappartitioning)
DataStream<String> stream = ...;
// apply the async I/O transformation
DataStream<Tuple2<String, String>> resultStream =
AsyncDataStream.unorderedWait(stream, new AsyncDatabaseRequest(), 1000, TimeUnit.MILLISECONDS, 100);
Edit:
As the user wants to create batches of size 100 and asyncio is specific to Streaming API for the moment, thus the best way would be to create countwindows with size 100.
Also, to purge the last window which might not have 100 events, custom Triggers could be used with a combination of Count Triggers and Time Based Triggers such that the trigger fires after a count of elements or after every few minutes.
A good follow up is available here on Flink Mailing List where the user "Kostya" created a custom trigger which is available here
I am trying to implement a simple RPC-like (or request-response) system over WebSockets in Java (there will be JS on the front-end but I am working on the back-end for now).
I am trying to apply the Java CompletableFuture pattern to handle sending messages asynchronously. But I am currnently stuck on error handling.
I have a class (let's call it the rpc class) that is responsible to send the message over a WebSocket session (using Spring WebSocket support classes here), then to wait for "reply" type messages, and matches them with the pending request and returning the content to the caller.
The flow is :
Client code calls the method on the rpc class, specifying the name of the procedure to call on the remote process, the session to which to send the message, and a map of arguments to send along.
The rpc class uses another lower level class to sends the message asynchronously using an Executor (thread pool), and receives a CompletableFuture<Void> for the "send the message" operation
It stores the pending request in a map, builds a CompletableFuture<Map<String, Object>> and associates it with the pending request, and stores them in a map. It returns the completable future.
When a "reply" type message is received, a method is called on the same class, this method tries to match the response with one of the pending requests (they have an ID for this) and then completes the CompletableFuture with the content received in the response.
So there are 3 threads involved : the caller thread, the thread that sends the message, and the thread that receives the message and completes the future.
Now, how should I handle an error in the sending of the message (e.g. IO error) in order to make the returned completableFuture also fail (or maybe implement a retry strategy, and a time out...) ?
Here is the code of the rpc class method that sends the message :
/**
* Invoke a remote procedure over WS on the specified session, with the given arguments.
* #param session The target session on which to send the RPC message
* #param target The name of the procedure to call
* #param arguments The arguments to be sent in the message
* #return
*/
public CompletableFuture<Map<String,Object>> invoke(WebSocketSession session, String target, Map<String, Object> arguments){
Invocation invocationMessage = new Invocation(target, arguments);
invocationMessage.setId(getNextId());
// completeable future for the result. It does nothing, will be completed when reply is received which happen in a different thread, see completeInvocation
CompletableFuture<Map<String, Object>> invocationFuture = new CompletableFuture<>();
CompletableFuture<Void> senderFuture = sender.sendMessage(session, invocationMessage);
// handle problem in the sending of the message
senderFuture.exceptionally(e -> {
// is this correct ??
invocationFuture.completeExceptionally(e);
return null;
});
// store the pending invocation in the registry
registry.addPendingInvocation(new PendingInvocation(invocationMessage, session, invocationFuture));
// return the future so the caller can have access to the result once it is ready
return invocationFuture;
}
The simplest way to do it would be to simply chain the futures using thencompose():
// completeable future for the result. It does nothing, will be completed when reply is received which happen in a different thread, see completeInvocation
CompletableFuture<Map<String, Object>> invocationFuture = new CompletableFuture<>();
CompletableFuture<Void> senderFuture = sender.sendMessage(session, invocationMessage);
// store the pending invocation in the registry
registry.addPendingInvocation(new PendingInvocation(invocationMessage, session, invocationFuture));
// return the future so the caller can have access to the result once it is ready
return senderFuture.thenCompose(__ -> invocationFuture);
In case of exceptional completion of senderFuture, the returned future will be completed exceptionally as well, with a CompletionException holding the exception as its cause (c.f. CompletionStage api).
Note that there are other concerns you might want to tackle as well:
Shouldn't you also cancel the pending invocation in case of exception?
What happens if the response arrives before addPendingInvocation is called? Shouldn't you call it before calling sendMessage to avoid issues?
Since you don't do anything with invocationFuture, wouldn't it be better to create it inside addPenidngInvocation?
I don't have much knowledge on Java EE but am currently learning it.
I've come up with a project which involves a long running task (up to several minutes) invoked by the user. The task consists of several steps. Of course I would like to show the progress to the user.
The project uses Java EE with JPA, JSF and Icefaces. It runs on Glassfish.
An experienced colleague adviced the following pattern to me:
Create a stateless, asynchronous EJB which creates a response object and processes the request
Persist the response object after each step
In the backing bean, query and display the response object
This works well. My only problem is to update the status site to mirror the progress. Currently I am doing this with a simple JavaScript page reload every x seconds.
Do you know a way/pattern to reflect the current step from the stateless ejb to the jsf backing bean?
Or, and I would prefer that, do you know a way to query the value of a backing bean every x seconds?
Edit:
I am aware of the Icefaces push mechanism, but I want the status update site to be decoupled from the calculation EJB for the following reasons:
The backing bean might already be destroyed because the user left the site and return later to fetch the result
Multiple sessions and therefore multiple beans may exist for one user
Having a clean design
There are several options to pass back this information. If EJB is living in the same JVM,
you may as well use some singleton Map and store progress under certain key (session ID)
If this is not the case, you will need some shared state or comminucation. There are several options
store it on database accessible from both tiers ( sql, JNDI, LDAP - better solution would be key-value store , like redis - if you got it )
use some messaging to deposit state of processing on web tier side
store state in a hash it on EJB tier side, and provide another SLSB method to rtrieve this state
Your choice is not easy - all of these solution suckin a different ways.
I accomplished this using a threaded polling model in conjunction with a ProgressBar component.
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
As you are using icefaces you could use the ICEpush mechanism for rendering your updates.
I create threads of class A and each sends a serialized object to a Server using ObjectOutputStream.
The Server creates new Threads B for each socket connection (whenever a new A client connects)
B will call a synchronized method on a Shared Resource Mutex which causes it (B) to wait() until some internal condition in the Mutex is true.
In this case how A can know that B is currently waiting?
Hope this description is clear.
Class Arrangement:
A1--------->B1-------->| |
A2--------->B2-------->| Mutex |
A3--------->B3-------->| |
EDIT:
it's a must to have wait(), notify() or notifyAll(), since this is for an academic project where concurrency is tested.
Normally A would read on the socket, which would "block" (i.e. not return, hang up) until some data was sent back by B. It doesn't need to be written to deal with the waiting status of B. It just reads and that inherently involves waiting for something to read.
Update So you want A's user interface to stay responsive. By far the best way to do that is take advantage of the user interface library's event queue system. All GUI frameworks have a central event loop that dispatches events to handlers (button click, mouse move, timer, etc.) There is usually a way for a background thread to post something to that event queue so that it will be executed on the main UI thread. The details will depend on the framework you're using.
For example, in Swing, a background thread can do this:
SwingUtilities.invokeAndWait(someRunnableObject);
So suppose you define this interface:
public interface ServerReplyHandler {
void handleReply(Object reply);
}
Then make a nice API for your GUI code to use when it wants to submit a request to the server:
public class Communications {
public static void callServer(Object inputs, ServerReplyHandler handler);
}
So your client code can call the server like this:
showWaitMessage();
Communications.callServer(myInputs, new ServerReplyHandler() {
public void handleReply(Object myOutputs) {
hideWaitMessage();
// do something with myOutputs...
}
});
To implement the above API, you'd have a thread-safe queue of request objects, which store the inputs object and the handler for each request. And a background thread which just does nothing but pull requests from the queue, send the serialised inputs to the server, read back the reply and deserialise it, and then do this:
final ServerReplyHandler currentHandler = ...
final Object currentReply = ...
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
currentHandler.handleReply(currentReply);
}
});
So as soon as the background thread has read back the reply, it passes it back into the main UI thread via a callback.
This is exactly how browsers do asynchronous communication from JS code. If you're familiar with jQuery, the above Communications.callServer method is the same pattern as:
showWaitMessage();
$.get('http://...', function(reply) {
hideWaitMessage();
// do something with 'reply'
});
The only difference in this case is that you are writing the whole communication stack by hand.
Update 2
You asked:
You mean I can pass "new ObjectOutputStream().writeObject(obj)" as
"myInputs" in Communications.callServer?
If all information is passed as serialised objects, you can build the serialisation into callServer. The calling code just passes some object that supports serialisation. The implementation of callServer would serialise that object into a byte[] and post that to the work queue. The background thread would pop it from the queue and send the bytes to the server.
Note that this avoids serialising the object on the background thread. The advantage of this is that all background thread activity is separated from the UI code. The UI code can be completely unaware that you're using threads for communication.
Re: wait and notify, etc. You don't need to write your own code to use those. Use one of the standard implementations of the BlockingQueue interface. In this case you could use LinkedBlockingQueue with the default constructor so it can accept an unlimited number of items. That means that submitting to the queue will always happen without blocking. So:
private static class Request {
public byte[] send;
public ServerReplyHandler handler;
};
private BlockingQueue<Request> requestQueue;
public static callServer(Object inputs, ServerReplyHandler handler) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
new ObjectOutputStream(byteStream).writeObject(inputs);
Request r = new Request();
r.send = byteStream.toByteArray();
r.handler = handler;
requestQueue.put(r);
}
Meanwhile the background worker thread is doing this:
for (;;) {
Request r = requestQueue.take();
if (r == shutdown) {
break;
}
// connect to server, send r.send bytes to it
// read back the response as a byte array:
byte[] response = ...
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
currentHandler.handleReply(
new ObjectInputStream(
new ByteArrayInputStream(response)
).readObject()
);
}
});
}
The shutdown variable is just:
private static Request shutdown = new Request();
i.e. it's a dummy request used as a special signal. This allows you to have another public static method to allow the UI to ask the background thread to quit (would presumably clear the queue before putting shutdown on it).
Note the essentials of the pattern: UI objects are never accessed on the background thread. They are only manipulated from the UI thread. There is a clear separation of ownership. Data is passed between threads as byte arrays.
You could start multiple workers if you wanted to support more than one request happening simultaneously.